반응형
반응형
반응형

이 글만을 통해서 기본적으로 텍스트를 출력하는 디스코드 봇을 만들 수 있습니다.

 

1. 봇 생성하고 초대하기

2. 코드 작성하기

3. 테스트 하기

 


 

봇 생성하고 초대하기

 

먼저 봇 계정을 생성해 주어야 합니다.

 

 

디스코드 홈페이지로 이동합니다. -> https://discordapp.com/

 

Discord — A New Way to Chat with Friends & Communities

Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.

discordapp.com

 

상단에 개발자 > 개발자 포털

 

 

 

 

New Application을 누릅니다.

 

 

 

 

이름을 설정하고 Create!

 

 

 

왼쪽 탭에서 Bot을 클릭하고, 오른쪽에 있는 Add Bot을 클릭하여 봇을 만들어 줍시다!

 

 

현재 페이지에서 봇의 프로필사진, 이름을 수정하실 수 있으며,

중요한 Token 값을 확인하실 수 있습니다. (절대 외부로 유출되서는 안됩니다. Regenerate버튼을 통해 재생성 가능합니다.)

Public Bot 설정은 아무나 이 봇을 초대할 수 있는지, 나만 초대할 수 있는지를 설정하는 것입니다.

체크가 해제되어 있다면, 나만 이 봇을 초대할 수 있습니다.

 

아래로 스크롤하면, 봇의 권한을 설저할 수 있는 탭이 나옵니다.

여기서 설정하지 않아도, 디스코드 서버 역할을 통해서 권한을 부여해 줄 수도 있습니다.

 

 

 

 

 

 

이제 봇 초대코드를 생성하겠습니다.

 

왼쪽 두번째 탭 OAuth2를 클릭하시고, 중간에 bot을 체크하시면 아래에 링크가 생성됩니다.

 

해당 링크로 접속하여 자신의 서버로 봇을 초대할 수 있습니다.

 

 

 

 

현재 봇은 오프라인 상태가 됩니다.

 


 

코드 작성하기

 

 

개발환경 : UBUNTU 18.04.3

개발언어: NODE JS V8

모듈 : discord.js v11

텍스트 에디터: ATOM (편하신거 사용하시면 됩니다.)

 

 

 

설치방법

 

 바로가기 <-- (https://github.com/discordjs/discord.js#installation)

 

 

먼저 npm과 node가 설치되어 있는지 확인해보세요.

node -v
npm -v

 

 

음성 봇을 사용하지 않는 경우

npm install discord.js

 


음성 봇을 사용할 경우

npm install discord.js opusscript

 

 

 

 

 

 

설치를 마쳤다면,

이제 텍스트 에디터로 가서 소스를 작성해 봅시다.

 

 

기본적인 소스는 다음과 같습니다. node_modules폴더가 있는 폴더에서 작업해주세요!

저는 파일명을 bot.js로 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Extract the required classes from the discord.js module
const { Client, Attachment } = require('discord.js');
 
// Create an instance of a Discord client
const client = new Client();
 
 
client.on('ready', () => {
  console.log(`Logged in as ${client.user.tag}!`);
});
 
client.on('message', msg => {
  if (msg.content.startsWith('r.help')) {
    msg.reply('Powered by node.js\nMade by M4ndU');
  }
 
  if (msg.content === 'r.whoami') {
    // Send the user's avatar URL
    msg.reply(msg.author.avatarURL);
  }
});
 
client.login('token');
 
cs

 

 

23행 token 자리에 디스코드 봇 관리 페이지에서 확인가능한 token 값을 넣어주시면 됩니다.

 

콘솔에 node bot.js을 입력해주시면 봇이 실행되면서, 디스코드 서버내에서 봇이 온라인 상태가 되는 것을 확인할 수 있습니다.

 

 

 

 

봇의 기능을 당담하는 12~21행의 내용을 분석해보겠습니다.

 

client.on('message', msg => {
  if (msg.content.startsWith('r.help')) {
    msg.reply('Powered by node.js\nMade by M4ndU');
  }

채팅창에 r.help로 시작하는 메세지를 보내면 메세지를 출력합니다.

Powered by node.js\nMade by M4ndU 이 부분을 수정하여 본인이 원하는 메세지를 넣을 수도 있습니다.

r.help를 수정하여 본인이 원하는 명령어로 변경하실 수도 있습니다.

 

 

 

if (msg.content === 'r.whoami') { 
    // Send the user's avatar URL 
    msg.reply(msg.author.avatarURL); 
  } 
});

메세지의 내용이 r.whoami와 동일하다면

그 유저의 정보를 보냅니다.

r.whoami를 수정하여 본인이 원하는 명령어로 변경하실 수도 있습니다.

msg.author.avatarURL 대신 'msg'로 자신이 원하는 메세지를 넣을 수도 있습니다.

 

 

msg.reply는 명령어를 입력한 사람을 언급과 함께 메세지를 보냅니다. 메세지만 보내고 싶으신 경우 msg.channel.send함수를 이용하시면 됩니다.

 

 

다음 포스트부터는 이 봇에 여러가지 기능을 추가해 보겠습니다.

반응형
반응형

1. npm으로 discord.js 설치 후 봇 실행시 발생하는 오류 해결

 

 

 

/Client.js:39
     } catch {
             ^

봇 실행시 위와 같은 오류가 발생할 경우입니다.

 

 

저같은 경우에는 discord.js github에 나와있는 설치방법으로 설치를 했을 경우에 발생하였습니다.

https://github.com/discordjs/discord.js#installation

 

discordjs/discord.js

A powerful JavaScript library for interacting with the Discord API - discordjs/discord.js

github.com

 

 

npm install discordjs/discord.js

 

 

 

 

이 명령어 대신에

https://discord.js.org/#/docs/main/stable/general/welcome

 

Discord.js

Discord.js is a powerful node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.

discord.js.org

이 문서에 나와있는 명령어를 사용하시면 됩니다.

 

 

npm install discord.js

 

 

 

자신의 node버전을 확인해서 12 이상으로 업데이트 하시면 됩니다.

 

 

 

 


 

 

2. 오디오 재생시 오디오가 재생되지 않고 바로 종료되는 문제

또는 Error: FFMPEG not found 에러 발생시

 

FFMPEG 설치

윈도우

npm install --save ffmpeg-binaries

 

리눅스

sudo apt install ffmpeg

 

 

 


 

3. opus 설치 오류

 

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-opus@0.3.2 install:
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the node-opus@0.3.2 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

 

 

이런 오류가 발생한다면, sudo를 두 번 사용해주면 된다.

sudo sudo npm install @discordjs/opus
반응형
반응형

30초 마다 경고창과 함께 크롬/파이어폭스로 특정 주소 창 띄우기

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@echo off
echo msgbox "아무거나 막 실행하지 말자",0,"수상한 프로그램" > msg.vbs
start /wait msg.vbs
del msg.vbs
 
:_loop
start chrome https://www.youtube.com/watch?v=zwhbV4LfBrc^&t=148s
start chrome https://mandu-mandu.tistory.com
start firefox https://www.youtube.com/watch?v=zwhbV4LfBrc^&t=148s
 
timeout 30 > NUL
 
echo msgbox "귀여우셔라",0,"o kawaii koto" > msg.vbs
start /wait msg.vbs
del msg.vbs
 
goto _loop
 
cs

 

 

위 코드 내용을 메모장에 붙여넣기 하고 파일명.bat 으로 저장하시면 됩니다.

한글을 사용하실 경우 인코딩은 ANSI로 설정하시면 됩니다.

 

 

 

 

Bat_To_Exe_Converter 를 이용해서 bat파일을 exe파일로 변환해줍니다.

 

 

'보이지않는 응용프로그램'으로 해두셔야 프로그램을 실행했을 때 콘솔창이 뜨지 않습니다.

 

 

 

 

 

프로그램 종료 방법


Ctrl + Shift + ESC = 작업관리자

 

세부정보 탭

 

실행한 프로그램명을 찾아서 [작업끝내기]

cmd.exe 찾아서 전부 [작업끝내기]

반응형
반응형

네이버 카페의 글 제목, 작성자 닉네임, 작성일을 파싱하는 코드입니다.

 

 

 

로그인 절차가 필요 없습니다.

 

게시판 페이지를 파싱합니다.

 

게시판 링크는 게시판 링크 우클릭해서 링크 복사 해서 /ArticleList.nhn 부분부터 복사하여

카페 링크 뒤에 붙이시면 됩니다.

 

 

 

추가 인자값들은 아래 코드에서 확인하세요. (userDisplay 이나 search.page 등)

 

 

 

 

simple_html_dom.php 파일을 필요로 합니다:

https://simplehtmldom.sourceforge.io/

 

PHP Simple HTML DOM Parser

$html = str_get_html(' Hello World '); $html->find('div', 1)->class = 'bar'; $html->find('div[id=hello]', 0)->innertext = 'foo'; echo $html; $html = file_get_html('http://slashdot.org/'); foreach($html->find('div.article') as $article) {     $item['title']

simplehtmldom.sourceforge.io

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
/*ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);*/
 
include($_SERVER['DOCUMENT_ROOT'].'simple_html_dom.php');
//simple_html_dom.php 파일 수정 필요합니다.
//https://mandu-mandu.tistory.com/358
 
 
function naver_cafe_article_parser($page_no){
  //작성자 M4ndU
 
  //카페 url
  //카페 링크 aaaaa처리
  //search.clubid, search.menuid 0 처리
  //하였기 때문에 본인 카페 링크및 게시판 확인하셔서 변경하셔야합니다.
  $url = "https://cafe.naver.com/aaaaa/ArticleList.nhn?search.clubid=000000000&search.boardtype=L&search.menuid=00&search.marketBoardTab=D%&search.specialmenutype=&userDisplay=50&search.page=".$page_no;
 
  $html = file_get_html($url);
 
  $board = $html->find('div[class=article-board m-tcol-c]');
  foreach ($board[1]->find('tr'as $article) {
 
    $article_title_link = $article->find('a[class=article]')[0];
    $article_title = $article_title_link->plaintext;
    $article_link = $article_title_link->href;
    $article_publisher = $article->find('td[class=p-nick]')[0]->plaintext;
    $article_date = $article->find('td[class=td_date]')[0]->innertext;
 
    if ($article_title == "") {
      continue;
    }
 
 
    echo "<tr>";
    echo "<td>".$article_title."</td>";
    echo "<td>".$article_publisher."</td>";
    echo "<td>".$article_date."</td>";
    echo "<td> https://cafe.naver.com/aaaaa".$article_link."</td>"//카페링크 aaaaa처리하였음. 본인이 변경하세요.
    echo "</tr>";
  }
}
?>
<!DOCTYPE html>
<html lang="kr" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <table class="table">
        <thead>
            <th>글제목</th>
            <th>작성자</th>
            <th>등록일시</th>
            <th>링크</th>
        </thead>
<?php
for ($i=1$i<10 ; $i++) { // 파싱할 게시판의 최대 페이지를 고려하세요.
  naver_cafe_article_parser($i);
}
?>
</table>
</body>
</html>
 
cs
반응형
반응형

국내 웹페이중에 charset이 KSC5601로 설정되어 있는 페이지들이 많다.

 

이 페이지를 simple_html_dom으로 파싱하려고 하면 아래와 같은 오류가 발생한다.

 

 

 

 

 

iconv(): Wrong charset, conversion from `KSC5601' to `UTF-8' is not allowed in simple_html_dom.php

 

 

 

 

 

 

이 경우 KSC5601을 CP949로 바꿔주면 해결된다.

 

 

 

simple_html_dom.php를 아래와 같이 수정해주자.

1
생략
784
785
786
787
789
790
791
792
793
794
795
생략
1724
<?php
...           
            if ((strcasecmp($targetCharset'UTF-8'== 0&& ($this->is_utf8($text)))
            {
                $converted_text = $text;
            }
            else
            {
              if ($sourceCharset == 'KSC5601') {
                $sourceCharset = 'CP949';
              }
                $converted_text = iconv($sourceCharset$targetCharset$text);
            }
...
?>
cs

791~793 삽입

반응형
반응형

해외결제는 당연하지만 표시된 금액보다 실제 지불 금액이 더 나온다.

환율에 따라 달라지기도 한다.

 

 


 

 

유튜브 프리미엄 7,900KRW/월

 

19년 12월 19일

실제 지불 금액 : 8,690KRW

 

이 전달에도 8690원이 지불되었기 때문에 금액은 고정인 것 같다.

 

(구글페이먼트코리아로 결제가 되는 걸 봐선 국내 결제인 듯 하다.)

 

 

 

 


 

 

 

 

디스코드 니트로 9.99USD/월

 

19년 11월 30일

실제 지불 금액 : 12,044KRW

 

카카오뱅크 체크 카드

 

상세:

현지 거래금액 USD 9.99

US 환산금액 USD 10.11

적용 환율 1,191.40

해외브랜드수수료 119KRW

해외이용수수료 23KRW

 


 

 

 

 

디스코드 니트로 클래식 4.99USD/월

 

19년 12월 30일

실제 지불 금액 : 5,895KRW

 

카카오뱅크 체크 카드

 

상세:

현지 거래금액 USD 4.99

US 환산금액 USD 5.05

적용 환율 1,167.70

해외브랜드수수료 58KRW

해외이용수수료 11KRW

 

 


 

 

 

마인크래프트 렐름 9,440KRW/월

 

19년 11월 19일

실제 지불 금액 : 9,681KRW

 

카카오뱅크 체크 카드

 

상세:

현지 거래금액 KRW 9,440 (원화 결제 괜찮은건가... 돈 더 나간건가)

US 환산금액 USD 8.21

적용 환율 1,179.30

해외브랜드수수료 94KRW

해외이용수수료 23KRW

 

 


 

 

 

 

해외결제는 환율 확인해서 결제해야할 것 같다.

반응형
반응형

 

종합 해킹툴이라고 거창해 보이지만 사실 기능은 몇가지 없다.

 

기능

 

0. 미세먼지 측정

1. 온습도 측정

-> lcd에 항상 값 표시

 

2. IR 센서로 신호 받고 IR LED로 받은 신호 그대로 보내기 (ex>적외선 리모컨 복사)

-> IR 센서는 항상 작동하도록하고 대신 스위치로 전류 차단 가능하게

-> IR LED는 버튼1 으로 제어 (버튼을 눌러 SEND MODE로 바꾸면, n초마다 작동) 

 

3. RFID 카드 복제 (MIFARE만 가능)

-> 스위치로 전류 차단 (MISO, 3.3v)

-> 메모리 부족 문제로, uid 복제기능만을 메인 코드에 넣고 데이터 복제 기능은 따로 코드 작성해서 사용할때만 업로드.

-> 버튼2 으로 모드 변경. (카드 읽기 모드, 쓰기 모드)

-> 버튼1과 버튼2를 동시에 누르면 카드 읽기/쓰기 작동 (카드를 올려놓고 눌러야함. 누르지 않으면 카드를 올려놓아도 무반응)

 

 

부가적으로

0. 버튼제어

-> 버튼 2개 사용

-> 아날로그 입력 핀 하나만을 사용. 저항을 이용해 누르는 버튼에 따라 전압값이 변함.

 

1. led로 상태표시

-> 네오픽셀 led 2개 사용

-> 1개는 미세먼지 농도값에 따라 변화

-> 다른 하나는 모드에 따라 변화

 

2. 조도센서로 led 밝기 제어

-> 만들고 나서 느낀점은 밝기 변화가 맘에 안듬.

 

3. oled 디스플레이 사용

-> 센서값, 모드 상태 표시

 

 

 

 

 


 

부품 구매

0. 아두이노 나노 호환보드

http://mechasolution.com/shop/goods/goods_view.php?goodsno=575878&category=

 

1. PMS7003 미세먼지 센서 + 어댑터

https://smartstore.naver.com/kitplus/products/3030053715?NaPm=ct%3Dk32ixhqg%7Cci%3D34ca3f3de4771118ec11a623302ec1b2002d5102%7Ctr%3Dsls%7Csn%3D713003%7Chk%3D84a16a182a71898f8dff9c0fccb4f0fe4b9f2a11

 

2. DHT22 온습도 센서

http://mechasolution.com/shop/goods/goods_view.php?goodsno=540038&category=129003

 

3. 적외선 수신부 / IR Receiver

http://mechasolution.com/shop/goods/goods_view.php?goodsno=211&category=

 

4. 적외선 LED 850nm 발신

http://mechasolution.com/shop/goods/goods_view.php?goodsno=540793&category=

 

5. RFID RC522

http://mechasolution.com/shop/goods/goods_view.php?goodsno=866&category=

 

6. 0.96인치 12864 OLED LCD 모듈 4핀

http://mechasolution.com/shop/goods/goods_view.php?goodsno=540942&category=

 

7. 네오픽셀 LED x2개

http://mechasolution.com/shop/goods/goods_view.php?goodsno=540705&category=

 

8. 버튼 x2개

http://mechasolution.com/shop/goods/goods_view.php?goodsno=542428&category=

 

9. 스위치 x3개

http://mechasolution.com/shop/goods/goods_view.php?goodsno=491&category=

 

10. 상황에 맞게 필요한 것들

1M저항, 1k저항 2개, S9013 npn tr

750옴 저항 http://mechasolution.com/shop/goods/goods_view.php?goodsno=951&category=044016001

20옴 저항 http://mechasolution.com/shop/goods/goods_view.php?goodsno=973&category=044016001

cds 조도센서

 

11. 만능기판

http://mechasolution.com/shop/goods/goods_view.php?goodsno=576100&category=132028

 

12. 브레드 보드 + 점퍼케이블

 

 

 

 

 

 

 


 

제작

 

핀 사용

 

아두이노 나노 부품
A3 A3 버튼
A4 SCL OLED 디스플레이
A5 SDA
A6 A6 CDS
D3   IR LED
D4 RX PMS7003
D5   IR receiver
D6 I 네오픽셀 LED
D7 TX PMS7003
D9 RST (7)

RFID RC522

()안에 숫자는 핀 순서

D10 SDA (1)
D11 MOSI (3)
D12 MISO (4)
D13 SCK (2)

 

 

 

 

ir led는 발신 거리가 매우 짧다. 따라서 증폭회로를 구성하여 발신 거리를 늘려야만 한다.

 

ir led 증폭 회로 :

https://mandu-mandu.tistory.com/336

 

 

 

 

 

버튼을 두 개달 수 있는 두 개의 남는 디지털핀이 없다. 따라서 하나의 아날로그 핀을 이용해서 버튼 두 개를 모두 연결해주었다.

 

참고:

http://blog.naver.com/PostView.nhn?blogId=heungmusoft&logNo=220607169389

 

저는 여기서 750옴 3개와 1M옴 1개를 사용하였습니다. 750옴 3개 대신에 저항값이 같은 저항 3개를 사용하셔도 됩니다.(아마...)

 

 

 

 

 

 

 

Fritzing 설계 및 제작

 

hacking_tool.fzz
0.07MB

 

oled 디스플레이 핀 연결을 왼쪽에서는 SCL SDA 무시하고 위치에 맞게 연결. 오른쪽에서는 SCL SDA 맞춰서 연결.

실제 부품에서 SCL과 SDA의 순서가 달라서 그렇습니다.

 

왼쪽 배치도에서 D5와 연결된 트렌지스터는 트렌지스터가 아니라, IR 수신부입니다.

 

 

추가가 필요한 부품 파일:

 

DHT22

RFID RC522

네오픽셀 led랑 pms7003이 파일이 없어서 다른 부품으로 대체했다.

 

 

 

 

 

 pcb프린팅해서 부품만 납땜하는게 젤 편할 듯 하다..

 

 

 

 

 

 

 

 

 

 


 

코드 작성

 

라이브러리에서 제공되는 예제 코드들을 활용했다.

 

 

센서랑 디스플레이는 아래 영상을 참고했다.

https://www.youtube.com/watch?v=yMIlVDL0C9s&t=224s

https://www.youtube.com/watch?v=qH650QLNrW4

 

 

메모리사용을 최대한 줄이기 위해서 시리얼 출력을 최대한 삭제하였다.

 

 

rfid 데이터 복제 기능을 따로 뺐기 때문에 코드는 2개로 나뉜다.

+ 두 개의 코드를 합친 코드도 같이 올렸다.

 

https://github.com/M4ndU/arduino

 

M4ndU/arduino

Hack tool made with Arduino. Contribute to M4ndU/arduino development by creating an account on GitHub.

github.com

 

project.ino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
//스케치는 프로그램 저장 공간 28950 바이트(94%)를 사용. 최대 30720 바이트.
//전역 변수는 동적 메모리 1414바이트(69%)를 사용, 634바이트의 지역변수가 남음.  최대는 2048 바이트.
#include <DHT.h>
#include <Adafruit_NeoPixel.h>
#include <U8g2lib.h>
#include <PMS.h>
#include <SoftwareSerial.h>
#include <IRremote.h>
#include <SPI.h>
#include <MFRC522.h>
 
 
#define NEO_PIN 6
#define DHT_PIN 2
#define IRrecvPin 5 // An IR detector/demodulator is connected to GPIO pin 5
#define cdsPin A6
#define buttonPin A3  // select the input pin for the potentiometer
#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above
 
 
 
SoftwareSerial pmsSerial(74); //RX, TX
PMS pms(pmsSerial);
PMS::DATA data;
 
byte pm25_status = 0;
byte pm100_status = 0;
 
 
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);
 
 
Adafruit_NeoPixel neoPixel = Adafruit_NeoPixel(2, NEO_PIN, NEO_GRB + NEO_KHZ800);
const int neo_color[][3= {{3232,32}, {0032}, {0320}, {32210}, {3200}, {1600}, {080}};
 
byte neo_color_index=0;
 
 
DHT dht(DHT_PIN, DHT22);
float temp;
float humi;
 
 
char IRDisplayStr;
char RFIDDisplayStr;
 
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
 
 
MFRC522::MIFARE_Key key;
 
byte newUid[10= {0xDE0xAD0xBE0xEF};
 
bool IsRfidWriteMode = false;
 
 
// ==================== start of IRrecv config ====================
IRrecv irrecv(IRrecvPin);
decode_results results;
byte size_of_rawdata;
uint16_t *raw_data;
// ==================== end of of IRrecv config ====================
 
 
 
// ==================== start of IRsend config ====================
IRsend irsend;  // An IR LED must be connected to Arduino PWM pin 3.
 
bool IRLED_SEND_SWITCH = false;
bool CLEAR_TO_SEND = false;
// ==================== end of of IRsend config ====================
 
 
//==================== start setup ====================
// This section of code runs only once at start-up.
void setup() {
  pinMode(cdsPin, INPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
 
  pmsSerial.begin(9600);
 
  dht.begin();
 
  u8g2.begin();
  u8g2.enableUTF8Print();
 
  neoPixel.begin();
  neoPixel.show();
 
  irrecv.enableIRIn();
 
  SPI.begin();                // Init SPI bus
  mfrc522.PCD_Init();         // Init MFRC522 card
}
//==================== end setup ====================
 
 
 
//==================== start rfid func ====================
void rfid_rw(bool w_mode) {
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    return;
  }
 
  if(!w_mode)
  {
    //dump_uid
     for (byte i = 0; i < mfrc522.uid.size; i++) {
      newUid[i] = mfrc522.uid.uidByte[i];
    }
 
    // Dump debug info about the card; PICC_HaltA() is automatically called
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
  }
  else
  {
      // Set new UID
      if ( mfrc522.MIFARE_SetUid(newUid, (byte)4true) ) {
        Serial.println(F("Wrote new UID to card."));
      }
 
       mfrc522.PICC_HaltA();       // Halt PICC
   }
 
}
//==================== end rifd func ====================
 
 
 
//==================== start loop func ====================
void loop() {
  if (irrecv.decode(&results)) {
    irrecv.resume();              // Prepare for the next value
    // resultToRawArray() allocates the memory we need for the array.
    raw_data = results.rawbuf;
    // Find out how many elements are in the array.
    size_of_rawdata = results.rawlen;
    CLEAR_TO_SEND = true;
  }
 
  if (IRLED_SEND_SWITCH){
    if (CLEAR_TO_SEND){
      irsend.sendRaw(raw_data, size_of_rawdata, 38);  // Send a raw data capture at 38kHz.
      delay(1000);
    }
    else {
      IRLED_SEND_SWITCH = false;
    }
  }
 
 
  int light = analogRead(cdsPin);
 
  int buttonValue = analogRead(buttonPin);
  if(buttonValue == 339) {
    IRLED_SEND_SWITCH = !IRLED_SEND_SWITCH;
  }
  if(buttonValue == 682) {
    IsRfidWriteMode = !IsRfidWriteMode;
  }
  if(buttonValue == 510) {
    rfid_rw(IsRfidWriteMode);
  }
 
  if (IRLED_SEND_SWITCH){
    IRDisplayStr = 'S';  //send mode
    neo_color_index = 5;
  } else{
    IRDisplayStr = 'P';
    neo_color_index = 0//normal
    }
  if(IsRfidWriteMode){
    RFIDDisplayStr = 'W'//write
    neo_color_index = 6;
  } else {
    RFIDDisplayStr = 'R'//read
    }
 
  neoPixel.setPixelColor(1, neoPixel.Color(neo_color[neo_color_index][0],neo_color[neo_color_index][1],neo_color[neo_color_index][2]));
 
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
  u8g2.firstPage();
  do{
 
    temp = dht.readTemperature();
    humi = dht.readHumidity();
 
    if (pms.read(data)) {
      if ((int) data.PM_AE_UG_2_5 < 9) {
        pm25_status = 1;
      }
      else if (8 < (int) data.PM_AE_UG_2_5 && (int) data.PM_AE_UG_2_5 < 26) {
        pm25_status = 2;
      }
      else if (25 < (int) data.PM_AE_UG_2_5 && (int) data.PM_AE_UG_2_5 < 76) {
        pm25_status = 3;
      }
      else if (75 < (int) data.PM_AE_UG_2_5) {
        pm25_status = 4;
      }
      if ((int) data.PM_AE_UG_10_0 < 16) {
        pm100_status = 1;
      }
      else if (15 < (int) data.PM_AE_UG_10_0 && (int) data.PM_AE_UG_10_0 < 51) {
        pm100_status = 2;
      }
      else if (50 < (int) data.PM_AE_UG_10_0 && (int) data.PM_AE_UG_10_0 < 150) {
        pm100_status = 3;
      }
      else if (149 < (int) data.PM_AE_UG_10_0) {
        pm100_status = 4;
      }
    }
 
    neoPixel.setBrightness(light); //light값을 잘 다뤄보세요...
    byte neo_status = max(pm25_status, pm100_status);
    neoPixel.setPixelColor(0, neoPixel.Color(neo_color[neo_status][0],neo_color[neo_status][1],neo_color[neo_status][2]));
    neoPixel.show();
 
    u8g2.setCursor(00);
    u8g2.print(F("T"));
    u8g2.setCursor(160);
    u8g2.print(temp);
    u8g2.setCursor(640);
    u8g2.print(F("H"));
    u8g2.setCursor(800);
    u8g2.print(humi);
    u8g2.setCursor(015);
    u8g2.print(F("pm1.0"));
    u8g2.setCursor(030);
    u8g2.print(F("pm2.5"));
    u8g2.setCursor(045);
    u8g2.print(F("pm10.0"));
    u8g2.setCursor(5415);
    u8g2.print(data.PM_AE_UG_1_0);
    u8g2.setCursor(5430);
    u8g2.print(data.PM_AE_UG_2_5);
    u8g2.setCursor(5445);
    u8g2.print(data.PM_AE_UG_10_0);
    u8g2.setCursor(11020);
    u8g2.print((String)IRDisplayStr);
    u8g2.setCursor(11035);
    u8g2.print((String)RFIDDisplayStr);
 
 
  }while(u8g2.nextPage());
}
//==================== end loop func ====================
 
cs

 

 

 

 

 

only_rfid_data_copy.ino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
//스케치는 프로그램 저장 공간 9272 바이트(30%)를 사용. 최대 30720 바이트.
//전역 변수는 동적 메모리 1436바이트(70%)를 사용, 612바이트의 지역변수가 남음.  최대는 2048 바이트. 
#include <Adafruit_NeoPixel.h>
#include <SPI.h>
#include <MFRC522.h>
 
 
 
#define NEO_PIN 6
#define cdsPin A6
#define buttonPin A3  // select the input pin for the potentiometer
#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above
#define MENU_STR "button 1.R/W 2.mode"
 
 
Adafruit_NeoPixel neoPixel = Adafruit_NeoPixel(2, NEO_PIN, NEO_GRB + NEO_KHZ800);
const PROGMEM int8_t neo_color[][3= {{3232,32}, {0032}, {0320}, {32210}, {3200}, {1600}, {080}};
 
int8_t neo_color_index=0;
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
 
byte buffer[18];
byte block;
byte waarde[64][16];
MFRC522::StatusCode status;
 
MFRC522::MIFARE_Key key;
 
// Number of known default keys (hard-coded)
// NOTE: Synchronize the NR_KNOWN_KEYS define with the defaultKeys[] array
#define NR_KNOWN_KEYS   8
// Known keys, see: https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys
byte knownKeys[NR_KNOWN_KEYS][MFRC522::MF_KEY_SIZE] =  {
    {0xff0xff0xff0xff0xff0xff}, // FF FF FF FF FF FF = factory default
    {0xa00xa10xa20xa30xa40xa5}, // A0 A1 A2 A3 A4 A5
    {0xb00xb10xb20xb30xb40xb5}, // B0 B1 B2 B3 B4 B5
    {0x4d0x3a0x990xc30x510xdd}, // 4D 3A 99 C3 51 DD
    {0x1a0x980x2c0x7e0x450x9a}, // 1A 98 2C 7E 45 9A
    {0xd30xf70xd30xf70xd30xf7}, // D3 F7 D3 F7 D3 F7
    {0xaa0xbb0xcc0xdd0xee0xff}, // AA BB CC DD EE FF
    {0x000x000x000x000x000x00}  // 00 00 00 00 00 00
};
 
byte newUid[10= {0xDE0xAD0xBE0xEF};
 
bool IsRfidWriteMode = false;
 
 
//==================== start setup ====================
// This section of code runs only once at start-up.
void setup() {
  pinMode(cdsPin, INPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
 
  while (!Serial);            // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();                // Init SPI bus
  mfrc522.PCD_Init();         // Init MFRC522 card
  Serial.println(MENU_STR);
 
  neoPixel.begin();
  neoPixel.show();
}
//==================== end setup ====================
 
 
 
//==================== start rfid func ====================
 
 //Via seriele monitor de bytes uitlezen in hexadecimaal
 
void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}
//Via seriele monitor de bytes uitlezen in ASCI
 
void dump_byte_array1(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.write(buffer[i]);
  }
}
 
/*
 * Try using the PICC (the tag/card) with the given key to access block 0 to 63.
 * On success, it will show the key details, and dump the block data on Serial.
 *
 * @return true when the given key worked, false otherwise.
 */
 
bool check_status_failed(MFRC522::StatusCode ck_status){
  if (ck_status != MFRC522::STATUS_OK) {
      Serial.print(F("failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return true;
  }
  return false;
}
 
void end_rc522_sign(){
  mfrc522.PICC_HaltA();       // Halt PICC
  mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
}
 
bool try_key(MFRC522::MIFARE_Key *key)
{
    bool result = false;
 
    for(byte block = 0; block < 64; block++){
 
    // Serial.println(F("Authenticating using key A..."));
    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, key, &(mfrc522.uid));
    if (check_status_failed(status)) {
        return false;
    }
 
    // Read block
    byte byteCount = sizeof(buffer);
    status = mfrc522.MIFARE_Read(block, buffer, &byteCount);
    if (!check_status_failed(status)) {
        // Successful read
        result = true;
        Serial.print(F("Succ key:"));
        dump_byte_array((*key).keyByte, MFRC522::MF_KEY_SIZE);
        Serial.println();
 
        //dump_uid
         for (int i = 0; i < mfrc522.uid.size; i++) {
          newUid[i] = mfrc522.uid.uidByte[i];
        }
 
        // Dump block data
        Serial.print(F("Block ")); Serial.print(block); Serial.print(F(":"));
        dump_byte_array1(buffer, 16); //omzetten van hex naar ASCI
        Serial.println();
 
        for (int p = 0; p < 16; p++//De 16 bits uit de block uitlezen
        {
          waarde [block][p] = buffer[p];
          Serial.print(waarde[block][p]);
          Serial.print(" ");
        }
 
        }
    }
    Serial.println();
 
    Serial.println(MENU_STR);
 
    end_rc522_sign();
    return result;
}
 
void rfid_rw(bool writemode) {
 
  Serial.println(F("Insert card..."));
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    return;
  }
 
  // Show some details of the PICC (that is: the tag/card)
  Serial.print(F("Card UID:"));
  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
  Serial.println();
  Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  Serial.println(mfrc522.PICC_GetTypeName(piccType));
 
  if(!writemode)
  {
    Serial.println(F("Read"));
    // Try the known default keys
    MFRC522::MIFARE_Key key;
    for (byte k = 0; k < NR_KNOWN_KEYS; k++) {
        // Copy the known key into the MIFARE_Key structure
        for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
            key.keyByte[i] = knownKeys[k][i];
        }
        // Try the key
        if (try_key(&key)) {
            // Found and reported on the key and block,
            // no need to try other keys for this PICC
            break;
        }
    }
 
  }
  else
  {
    Serial.println(F("Copy to the new card"));
    for (byte i = 0; i < 6; i++) {
      key.keyByte[i] = 0xFF;
    }
 
    for(int i = 4; i <= 62; i++){ //De blocken 4 tot 62 kopieren, behalve al deze onderstaande blocken (omdat deze de authenticatie blokken zijn)
      if(i == 7 || i == 11 || i == 15 || i == 19 || i == 23 || i == 27 || i == 31 || i == 35 || i == 39 || i == 43 || i == 47 || i == 51 || i == 55 || i == 59){
        i++;
      }
      block = i;
 
        // Authenticate using key A
      Serial.println(F("Authenticating using key A..."));
      status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
      if (check_status_failed(status)) {
          return;
      }
 
      // Authenticate using key B
      Serial.println(F("Authenticating again using key B..."));
      status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, block, &key, &(mfrc522.uid));
      if (check_status_failed(status)) {
          return;
      }
 
      /*
      // Set new UID
      if ( mfrc522.MIFARE_SetUid(newUid, (byte)4, true) ) {
        Serial.println(F("Wrote new UID to card."));
      }
      */
 
      // Write data to the block
      Serial.print(F("Writing data into block "));
      Serial.print(block);
      Serial.println("\n");
 
      dump_byte_array(waarde[block], 16);
 
 
       status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(block, waarde[block], 16);
       check_status_failed(status);
 
 
       Serial.println("\n");
 
    }
    end_rc522_sign();
    Serial.println(MENU_STR);
  }
}
//==================== end rfid func ====================
 
 
 
 
//==================== start loop func ====================
void loop() {
 
  int8_t light = analogRead(cdsPin);
  int8_t brightness = map(light/2010242550);
 
  int16_t buttonValue = analogRead(buttonPin);
  if(buttonValue == 339) {
    rfid_rw(IsRfidWriteMode);
  }
  if(buttonValue == 682) {
    IsRfidWriteMode = !IsRfidWriteMode;
  }
 
  if (IsRfidWriteMode){
    neo_color_index = 5;
  } else{
    neo_color_index = 0//READ MODE
    }
  neoPixel.setPixelColor(1, neoPixel.Color(neo_color[neo_color_index][0],neo_color[neo_color_index][1],neo_color[neo_color_index][2]));
  neoPixel.setBrightness(brightness);
  neoPixel.show();
 
}
//==================== end loop func ====================
 
cs

 

all.ino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
//스케치는 프로그램 저장 공간 25636 바이트(83%)를 사용. 최대 30720 바이트.
//전역 변수는 동적 메모리 2410바이트(117%)를 사용, -362바이트의 지역변수가 남음.  최대는 2048 바이트.
#include <DHT.h>
#include <Adafruit_NeoPixel.h>
#include <U8g2lib.h>
#include <PMS.h>
#include <SoftwareSerial.h>
#include <IRremote.h>
#include <SPI.h>
#include <MFRC522.h>
 
 
#define NEO_PIN 6
#define DHT_PIN 2
#define IRrecvPin 5 // An IR detector/demodulator is connected to GPIO pin 5
#define cdsPin A6
#define buttonPin A3  // select the input pin for the potentiometer
#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above
 
 
 
SoftwareSerial pmsSerial(74); //RX, TX
PMS pms(pmsSerial);
PMS::DATA data;
 
byte pm25_status = 0;
byte pm100_status = 0;
 
 
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);
 
 
Adafruit_NeoPixel neoPixel = Adafruit_NeoPixel(2, NEO_PIN, NEO_GRB + NEO_KHZ800);
const int neo_color[][3= {{3232,32}, {0032}, {0320}, {32210}, {3200}, {1600}, {080}};
 
byte neo_color_index=0;
 
 
DHT dht(DHT_PIN, DHT22);
float temp;
float humi;
 
 
char IRDisplayStr;
char RFIDDisplayStr;
 
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
 
byte buffer[18];
byte block;
byte waarde[64][16];
MFRC522::StatusCode status;
 
MFRC522::MIFARE_Key key;
 
// Number of known default keys (hard-coded)
// NOTE: Synchronize the NR_KNOWN_KEYS define with the defaultKeys[] array
#define NR_KNOWN_KEYS   8
// Known keys, see: https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys
byte knownKeys[NR_KNOWN_KEYS][MFRC522::MF_KEY_SIZE] =  {
    {0xff0xff0xff0xff0xff0xff}, // FF FF FF FF FF FF = factory default
    {0xa00xa10xa20xa30xa40xa5}, // A0 A1 A2 A3 A4 A5
    {0xb00xb10xb20xb30xb40xb5}, // B0 B1 B2 B3 B4 B5
    {0x4d0x3a0x990xc30x510xdd}, // 4D 3A 99 C3 51 DD
    {0x1a0x980x2c0x7e0x450x9a}, // 1A 98 2C 7E 45 9A
    {0xd30xf70xd30xf70xd30xf7}, // D3 F7 D3 F7 D3 F7
    {0xaa0xbb0xcc0xdd0xee0xff}, // AA BB CC DD EE FF
    {0x000x000x000x000x000x00}  // 00 00 00 00 00 00
};
 
byte newUid[10= {0xDE0xAD0xBE0xEF};
 
bool IsRfidWriteMode = false;
 
 
// ==================== start of IRrecv config ====================
IRrecv irrecv(IRrecvPin);
decode_results results;
byte size_of_rawdata;
uint16_t *raw_data;
// ==================== end of of IRrecv config ====================
 
 
 
// ==================== start of IRsend config ====================
IRsend irsend;  // An IR LED must be connected to Arduino PWM pin 3.
 
bool IRLED_SEND_SWITCH = false;
bool CLEAR_TO_SEND = false;
// ==================== end of of IRsend config ====================
 
 
//==================== start setup ====================
// This section of code runs only once at start-up.
void setup() {
  pinMode(cdsPin, INPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
 
  pmsSerial.begin(9600);
 
  dht.begin();
 
  u8g2.begin();
  u8g2.enableUTF8Print();
 
  neoPixel.begin();
  neoPixel.show();
 
  irrecv.enableIRIn();
 
  SPI.begin();                // Init SPI bus
  mfrc522.PCD_Init();         // Init MFRC522 card
}
//==================== end setup ====================
 
 
 
//==================== start rfid func ====================
bool check_status_failed(MFRC522::StatusCode ck_status){
 if (ck_status != MFRC522::STATUS_OK) {
     Serial.print(F("failed: "));
     Serial.println(mfrc522.GetStatusCodeName(status));
     return true;
 }
 return false;
}
 
void rc522_epil(){
 mfrc522.PICC_HaltA();       // Halt PICC
 mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
}
 
bool try_key(MFRC522::MIFARE_Key *key)
{
  bool result = false;
 
  for(byte block = 0; block < 64; block++){
 
     // Serial.println(F("Authenticating using key A..."));
    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, key, &(mfrc522.uid));
    if (check_status_failed(status)) {
       return false;
     }
 
    // Read block
    byte byteCount = sizeof(buffer);
    status = mfrc522.MIFARE_Read(block, buffer, &byteCount);
    if (!check_status_failed(status)) {
       // Successful read
       result = true;
 
       //dump_uid
        for (byte i = 0; i < mfrc522.uid.size; i++) {
         newUid[i] = mfrc522.uid.uidByte[i];
       }
 
       // Dump block data
       for (byte p = 0; p < 16; p++)
       {
         waarde [block][p] = buffer[p];
       }
 
     }
  }
  rc522_epil();
  return result;
}
 
void rfid_rw(bool w_mode) {
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    return;
  }
 
  if(!w_mode)
  {
    // Try the known default keys
    MFRC522::MIFARE_Key key;
    for (byte k = 0; k < NR_KNOWN_KEYS; k++) {
        // Copy the known key into the MIFARE_Key structure
        for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
            key.keyByte[i] = knownKeys[k][i];
        }
        // Try the key
        if (try_key(&key)) {
            // Found and reported on the key and block,
            // no need to try other keys for this PICC
            break;
        }
    }
 
  }
  else
  {
    for (byte i = 0; i < 6; i++) {
      key.keyByte[i] = 0xFF;
    }
 
    for(byte i = 4; i <= 62; i++){
      if(i == 7 || i == 11 || i == 15 || i == 19 || i == 23 || i == 27 || i == 31 || i == 35 || i == 39 || i == 43 || i == 47 || i == 51 || i == 55 || i == 59){
        i++;
      }
      block = i;
 
      // Authenticate using key A
      status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
      if (check_status_failed(status)) {
          return;
      }
 
      // Authenticate using key B
      status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, block, &key, &(mfrc522.uid));
      if (check_status_failed(status)) {
          return;
      }
 
      /*
      // Set new UID
      if ( mfrc522.MIFARE_SetUid(newUid, (byte)4, true) ) {
        Serial.println(F("Wrote new UID to card."));
      }
      */
 
      // Write data to the block
       status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(block, waarde[block], 16);
       check_status_failed(status);
    }
    rc522_epil();
  }
}
 
 
//==================== end rifd func ====================
 
 
 
//==================== start loop func ====================
void loop() {
  if (irrecv.decode(&results)) {
    irrecv.resume();              // Prepare for the next value
    // resultToRawArray() allocates the memory we need for the array.
    raw_data = results.rawbuf;
    // Find out how many elements are in the array.
    size_of_rawdata = results.rawlen;
    CLEAR_TO_SEND = true;
  }
 
  if (IRLED_SEND_SWITCH){
    if (CLEAR_TO_SEND){
      irsend.sendRaw(raw_data, size_of_rawdata, 38);  // Send a raw data capture at 38kHz.
      delay(1000);
    }
    else {
      IRLED_SEND_SWITCH = false;
    }
  }
 
 
  int16_t light = analogRead(cdsPin);
  int16_t brightness = map(light / 2010242550);
 
  int16_t buttonValue = analogRead(buttonPin);
  if(buttonValue == 339) {
    IRLED_SEND_SWITCH = !IRLED_SEND_SWITCH;
  }
  if(buttonValue == 682) {
    IsRfidWriteMode = !IsRfidWriteMode;
  }
  if(buttonValue == 900) {
    rfid_rw(IsRfidWriteMode);
  }
 
  if (IRLED_SEND_SWITCH){
    IRDisplayStr = 'S';
    neo_color_index = 5;
  } else{
    IRDisplayStr = 'P';
    neo_color_index = 0//normal
    }
  if(IsRfidWriteMode){
    RFIDDisplayStr = 'W';
    neo_color_index = 6;
  } else {
    RFIDDisplayStr = 'R';
    }
 
  neoPixel.setPixelColor(1, neoPixel.Color(neo_color[neo_color_index][0],neo_color[neo_color_index][1],neo_color[neo_color_index][2]));
 
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
  u8g2.firstPage();
  do{
 
    temp = dht.readTemperature();
    humi = dht.readHumidity();
 
    if (pms.read(data)) {
      if ((int) data.PM_AE_UG_2_5 < 9) {
        pm25_status = 1;
      }
      else if (8 < (int) data.PM_AE_UG_2_5 && (int) data.PM_AE_UG_2_5 < 26) {
        pm25_status = 2;
      }
      else if (25 < (int) data.PM_AE_UG_2_5 && (int) data.PM_AE_UG_2_5 < 76) {
        pm25_status = 3;
      }
      else if (75 < (int) data.PM_AE_UG_2_5) {
        pm25_status = 4;
      }
      if ((int) data.PM_AE_UG_10_0 < 16) {
        pm100_status = 1;
      }
      else if (15 < (int) data.PM_AE_UG_10_0 && (int) data.PM_AE_UG_10_0 < 51) {
        pm100_status = 2;
      }
      else if (50 < (int) data.PM_AE_UG_10_0 && (int) data.PM_AE_UG_10_0 < 150) {
        pm100_status = 3;
      }
      else if (149 < (int) data.PM_AE_UG_10_0) {
        pm100_status = 4;
      }
    }
 
    neoPixel.setBrightness(brightness);
    byte neo_status = max(pm25_status, pm100_status);
    neoPixel.setPixelColor(0, neoPixel.Color(neo_color[neo_status][0],neo_color[neo_status][1],neo_color[neo_status][2]));
    neoPixel.show();
 
    u8g2.setCursor(00);
    u8g2.print(F("T"));
    u8g2.setCursor(160);
    u8g2.print(temp);
    u8g2.setCursor(640);
    u8g2.print(F("H"));
    u8g2.setCursor(800);
    u8g2.print(humi);
    u8g2.setCursor(015);
    u8g2.print(F("pm1.0"));
    u8g2.setCursor(030);
    u8g2.print(F("pm2.5"));
    u8g2.setCursor(045);
    u8g2.print(F("pm10.0"));
    u8g2.setCursor(5415);
    u8g2.print(data.PM_AE_UG_1_0);
    u8g2.setCursor(5430);
    u8g2.print(data.PM_AE_UG_2_5);
    u8g2.setCursor(5445);
    u8g2.print(data.PM_AE_UG_10_0);
    u8g2.setCursor(11020);
    u8g2.print((String)IRDisplayStr);
    u8g2.setCursor(11035);
    u8g2.print((String)RFIDDisplayStr);
 
 
  }while(u8g2.nextPage());
}
//==================== end loop func ====================
 
cs

 

 

 

반응형
반응형

ESP8266 NodeMCU을 이용해서 wifi 공격도구를 만들 수 있다.

 

 

이 도구의 주요 공격은 deauthentication attack (인증 해제 공격) 이다.

 

 

 

IEEE 802.11 표준의 큰 취약점을 이용한 것으로, 인증 해제 패킷만 뿌리기만 하면 기기의 와이파이 연결이 해제된다.

deauthentication 패킷을 뿌리는 시간동안 와이파이 연결이 계속 끊기게 되므로, 사실상 해당 와이파이를 사용할 수 없게 되는 것이다.

 

 

이 취약점을 해결하기 위해 2009년에 802.11w라는 것이 나왔는데 이 기술이 적용된 제품은 매우 극소수이다.

 

 

 

이 프로젝트의 목적에는 해당 취약점이 있는 회사가 해당 문제를 해결하게 하는 데에 있다고 한다.

 

 

 

 


 

 

 

 

 

 

깃 허브에도 나와있지만,  deauthentication attack 은 zamming(재밍) 이 아니다.

공유기가 사용하는 2.4Ghz나 5Ghz 주파수 대역을 방해하는 방식이 아니다.

 

 

재밍은 전파법에 걸린다. 하지말자.

deauth공격도 반드시 허가 받은 기기에만 시도하자.

 

 

단순히 deauth 패킷만 뿌릴 뿐이다.

(패킷하나 날렸다고 해당 공유기를 사용하는 이용자들의 와이파이 연결을 끊을 수 있다니..)

 

 

 

 

 


 

 

 

 

제작에 대해서는 사실 이 글에서 설명할 것이 없다

 

 

위키에 다 나와있어서 그대로 따라하면 된다.

https://github.com/spacehuhn/esp8266_deauther/wiki

 

spacehuhn/esp8266_deauther

Cheap WiFi hacks. Contribute to spacehuhn/esp8266_deauther development by creating an account on GitHub.

github.com

https://github.com/spacehuhn/esp8266_deauther

 

spacehuhn/esp8266_deauther

Cheap WiFi hacks. Contribute to spacehuhn/esp8266_deauther development by creating an account on GitHub.

github.com

 

 

 

나는 l2c로 작동하는 oled display, 네오픽셀 led, 버튼 3개를 구입했다.

 

 

spi방식의 oled 디스플레이를 구매하면, 연결해야되는 핀 개수가 늘어난다. 그러면 납땜할때 귀찮아진다.. 그냥 l2c 방식으로 구매하는 것을 권장한다.

 

네오픽셀 led는 현재 작동 상태를 보여준다.

 

버튼은 3개~6개까지 달 수 있다.

기본 : UP, DOWN, A

추가 : BACK, LEFT, RIGHT 

 

 

 

테스트를 위해 브레드보드와 점퍼케이블도 구매하자.

 

 

0. NodeMCU V1.0 Lua WiFi ESP8266

http://mechasolution.com/shop/goods/goods_view.php?goodsno=539585&category=

 

1. 버튼

http://mechasolution.com/shop/goods/goods_view.php?goodsno=542428&category=

 

2. 네오픽셀 led

http://mechasolution.com/shop/goods/goods_view.php?goodsno=540705&category=

 

3. 0.96인치 12864 OLED LCD 모듈 4핀

http://mechasolution.com/shop/goods/goods_view.php?goodsno=540942&category=

 

4. 브레드보드 400핀 - 하프사이즈

http://mechasolution.com/shop/goods/goods_view.php?goodsno=7&category=

 

5. 점퍼케이블

20cm를 사용했었는데 충분하다.

 

 

 

 

 

만능기판에 전부 납땜해서 연결을 해주었다.

.납땝할 때 사용한 선은 집에 굴러다니던 선 잘라서 사용했다.

.철사로 해봤는데 잘 안된다.

.케이블에서 나온 전선 부분을 동그랗게 올가미 형태로 해주면 납땜이 잘 된다.

스위치 하나를 SD3에 연결했다. 납땜 후 제대로 작동을 안해서,,  글루건으로 고정해주었다.

 

집에 버튼 남아서 back용으로 하나 더 달아주었다.

 

 

 


 

 

사용 방법은 3가지가 있다. 

시리얼, 웹, oled 디스플레이

 

 

시리얼을 이용하면 여러 명령어를 사용할 수 있다.

다만, 반드시 컴퓨터와 usb로 연결해서 시리얼 모니터를 열어야만 한다.

 

 

 

은 컴퓨터와 usb로 연결하지 않고 와이파이로 연결해서 웹페이지를 이용해 제어할 수 있다.

그래서 기기와 스마트폰만을 가지고 휴대하면서 사용할 수 있게 해준다.

하지만 기기의 와이파이에 접속해야한다는 불편함이 있다. (+ 당연히 인터넷이 안된다.)

 

 

 

 

 

기기에 oled display, 버튼3개이상을 달아주면 기기만 가지고 제어를 할 수 있다.

 

메인 메뉴를 보면 5가지가 있다.

 

 

SCAN

스캔을 통해 공격할 대상을 찾는다.

 

SCAN AP + ST

SCAN APs

SCAN Stations

 

세 가지가 있는데, AP는 공유기, Stations는 휴대기기? 인 것 같다.

 

 

SELECT

스캔으로 찾은 목록을 보여주며, 이 곳에서 공격할 대상을 지정할 수 있다.

 

 

ATTACK

공격을 할 수 있다. 세 가지의 공격이 있다.

 

deauth는 인증 해제

beacon은 가짜 와이파이를 비콘을 뿌린다. 연결을 시도하면 연결이 되지 않는다.

어! 무료 와이파이이다! 하고 연결을 시도하면 연결이 되지 않는 그러한 공격

probe는 아직 잘 모르겠다. 연결 잘 되던데..?

 

 

PACKET MONITOR

선택한 채널에 돌아다니는(?) 패킷의 양을 보여준다.

 

CLOCK

그냥 시계인데, 전원을 끈 시간동안은 시계가 멈추기 때문에 전원을 계속 주고 있어야 한다.

반응형
반응형

아두이노에 사용되는 ir led의 발신거리가 매우 짧다. 무선이라는 의미가 없을 정도로.

 

하지만 트랜지스터를 이용한다면 1m이상 늘릴 수 있다!

 

 

 

 

집에 굴러다니던 트랜지스터를 이용했다.

 

 

 

 

 

 

S9013 NPN TR

750Ω 저항

5Ω 저항

 

 

 

 

 

D3 5V GND          ir led는 무조건 D3에 연결해야 한다. 

 

 

 

 

 

 

반응형
반응형

결론부터 말하면,

코드는 완벽(?)했는데 메모리 부족문제가 발생했고

 

회로도는 문제가 없는데.. 브레드보드에 테스트할 때도 문제가 없었는데

납땜하고 나서 문제가 생겼다.

 

 

 

 

 

 

 

 

 

 

내가 아두이노에 관심이 생긴 것은 코드게이트 2018 때 였다.

 

그 때 주제가 'IOT와 스마트 시티'였나..?

그래서 운영되는 부스들이 그 쪽과 관련된 내용들이었는데, 그 중에서 아두이노랑 CAN통신 모듈을 이용해서 자동차 계기판을 조작하는 부스에 참여를 했었다. 그 때 처음 아두이노를 다뤄보고 아두이노 IDE를 깔았었다. 다른 부스에서는 적외선 신호값을 읽어서 그대로 보내는 리모컨 복제(?)하는 거에도 시도를 했었다. 이때 값을 읽는 것은 성공했었는데, 다시 보내는걸 실패했어서 그런지 이 이후로 아두이노와 적외선쪽으로 건들여보고 싶다는 생각을 계속 해두고 있었다.

 

 

 

2학년때 와이파이 패킷 스니핑으로 시도를 했었고 이게 나중에 아두이노에 달리는 와이파이모듈로도 가능하지 않을까. 못해도 deauth패킷 날리는 것정도는 가능하지 않을까라는 생각을 가져왔다. (여기에다가 적외선 신호 복사기능까지 넣는다면?!)

 

 

 

19회 해킹캠프때 무승님의 RFID 발표를 너무 재밌게 들었고, 아두이노에 연결할 수 있는 rc522를 알게 되어 MIFARE Classic 카드 정도는 간단히 복제가 되지 않을까 라는 생각으로 "해킹툴" 기능에 추가를 했다.

 

 

 

3학년 2학기때 본격적으로 위 아이디어를 실현시키기 위해 부품들을 알아보고 구매를 했다.

처음에는 와이파이쪽 도구를 만들기 위해서 아두이노에 와이파이모듈을 달 생각이었다. 그런데 esp8266이 달려있는 nodemcu라는게 있었고, 이걸로 이미 deauther을 만드신 분이 계셨다.

 

https://github.com/spacehuhn/esp8266_deauther 

 

spacehuhn/esp8266_deauther

Cheap WiFi hacks. Contribute to spacehuhn/esp8266_deauther development by creating an account on GitHub.

github.com

 

 

 

 

그래서 nodemcu로 구매를 하고 위 소스코드에 IR과 RIFD를 제어할 코드를 추가해서 deauther은 web으로 제어를 하고 deauther을 제어하는 cli를 막고 ir과 rfid를 cli로 제어할 생각이었다.

 

 

 

ir receiver와 ir led를 시리얼로 제어해서 신호를 받고 다시 보내는 코드를 작성했고, 테스트에 성공했다.

 

다시, 모든 연결을 빼고 rc522만 달아서 카드를 읽고 복제하는 코드를 작성했고, 테스트에 성공했다.

 

 

 

이 두 개를 합치는 과정에서 문제가 발생했다.

 

두 개를 합친 코드는 문제가 없었다. nodemcu 핀사용에 문제가 있었다.

 

 

D0 부터 D8까지 내 맘대로 이용해먹을 수 있는 건줄 알았는데.. 아니었다.

 

 

 

D0는 sleep모드 wake용

D3은 플래시 버튼에 사용되고

D4, D8은 풀업저항필요

 

D1, D2, D5, D6, D7만이 범용으로 사용가능한 핀이었다.

 

 

IR에서 각 핀 하나씩, 총 2개를 사용하게 되고, rc522모듈이 5개의 핀을 사용하게 되어 2개의 핀이 오버가 된다. 오버된 핀을 아무 디지털 핀에 꼽고서 코드를 업로드 했을 때 업로드가 되지 않는 문제가 발생하였다.

 

(지금와서 생각난건데, deauther에서 네오픽셀 led를 SD2에 연결한다. SD1~3 이거 범용사용 되는거 아닌가?? 모르겠다. 아니 근데 deauther에 있는 위키에서는 sd2랑 sd3가 Flash에 사용된다고 써있네?)

 

 

 

 

 

 

그래서 만들던 프로젝트를 다시 구성해야 했다.

 

 

먼저, nodemcu로는 deauther만 구동하도록 했다. 위키 따라해서 만들었다. 납땜질할땐 버튼하나 더 늘렸다. back용으로.

 

위키:

https://github.com/spacehuhn/esp8266_deauther/wiki/Setup-Display-&-Buttons

 

spacehuhn/esp8266_deauther

Cheap WiFi hacks. Contribute to spacehuhn/esp8266_deauther development by creating an account on GitHub.

github.com

 

제작:

https://mandu-mandu.tistory.com/337

 

아두이노로 해킹도구 만들기 (1) - esp8266 deauther

 

mandu-mandu.tistory.com

 

 

 

브레드보드:

 

만능기판:

 

납땜 후 글루건으로 더 고정해주었다.

 

 

 

 

 

 

 

 

 

그리고 떨어져 나온 ir과 rfid는 사용가능한 핀 개수가 많은 아두이노 나노를 이용하기로 했다.

(아두이노 나노로 바꾸면서 ir관련한 코드를 아두이노나노에 맞게 바꿔주는 작업을 해야했다.)

근데 사용가능한 핀이 많은 아두이노 나노에 핀 7개만 쓰기에는 조금 아까워서 여러 기능들을 추가하기로 했다.

https://mandu-mandu.tistory.com/338

 

아두이노로 해킹도구 만들기 (2) - 미세먼지 센서 + IR + RFID

 

mandu-mandu.tistory.com

 

 

1. 미세먼지 센서 + 온습도 센서 + OLED 디스플리이 + 네오픽셀 LED + CDS 센서

 

심프팀 영상을 보고 만들고 싶어서 추가하게 되었다.

https://www.youtube.com/watch?v=yMIlVDL0C9s&t=224s

https://www.youtube.com/watch?v=qH650QLNrW4

 

평상시엔 미세먼지 센서로 위장할 수 있잖아?

 

 

CDS 조도센서는 달 생각이 없었는데, 집에 굴러다니길레 추가해주었다.

 

 

 

2. 스위치

안쓰는 모듈 전원 차단

 

 

 

3. 버튼과 네오픽셀 LED

버튼은 시리얼을 사용하지 않고 버튼만으로 ir이나 rfid를 제어할 수 있도록 추가를 해주었다.

 

네오픽셀 LED를 또 추가한 이유는 위에서 사용한 네오픽셀 LED는 미세먼지 상태 인디케이터이고, 이 네오픽셀 LED는 모듈이 어떤 상태인지 알려주는 용도이다.

 

 

 

 

 

 

 

다 구매하고 연결해서 코드를 다 짜고서,, 코드만 업로드 하면 되는데,

여기서 nodemcu에서는 신경도 쓰지 않았던 메모리 부족현상이 터진다.

 

rfid cloner 하나만 해도 메모리를 다 와그작 먹어버렸다.

 

메모리 문제해결을 위해 문자열 최소로 남기고 F() 사용해서 롬으로 넘기고 자료형을 가능한 타이트하게 했지만 역부족이었다. 모든 변수를 롬으로 넘겨서 사용하면 되지 않을까 싶기도 한데, 속도가 느리고, 읽고 쓰는게 너무 불편했다,

 

결국 나머지 모든 기능 과 rfid clone기능을 분리하기로 해서 rfid clone을 사용할 때에는 rfid clone 코드를 업로드 하는 방식으로 사용하기로 했다.

 

와! 메모리 문제는 해결을 했다.

 

 

 

브레드보드:

 

만능기판:

 

백엔드는 원래 지저분한거다

 

 

 

 

 

 

 

이제 새로운 문제는 만능기판에 납땜을 하고서 터진다.

 

브레드보드에 연결해서 테스트했을때에는 전혀 문제가 없었다.

내 납땜실력이 똥이라서 쇼트가 난건지, 기판에 달기 위해 새로 부품 배치도나 회로도를 다시 설계한게 문제인건지는 모르겠지만 아래와 같은 문제들이 생겼다.

 

 

nodemcu를 사용한 deauther의 경우

0. 1번째 버튼 무반응.

해결 : 1번째 버튼은 SD3핀으로 재연결

 

 

1. 2번쩨 버튼 계속 입력되고 있는 현상

해결 : 그냥 해당 핀으로 입력 안받게 해서 2번째 버튼 미사용. (나중에 2번째 버튼도 SD1으로 옮겨줘봐야겠다.)

 

 

작동에 문제가 없도록 해결 가능했다.

 

 

 

 

 

 

아두이노 나노를 사용한 종합 도구(?)의 경우

0. 아날로그 버튼 문제

저항과 아날로그 입력을 이용해서 버튼 입력에 따라 전압이 다르게 입력이 되는 것을 이용한 것인데, 두 개 버튼이 동시에 눌리고 있는 것으로 계속 입력이 되었다. 

 

설계상 문제인건지 전류가 어디로 새는건지.. 난 못찾았다.

해결 : 못했다.

 

 

1. rc522 스위치 제어 문제

이건 내 테스트 부족문제이기도 하다.

rc522에서 MOSI 와 3.3v 연결을 끊으면 rc522의 led가 완전히 꺼짐을 찾아내서 해당 부분에 스위치를 달아줬다.

 

근데 문제는 연결이 끊겨있는 상태에서 아두이노 나노가 부팅이 되면 led가 들어오고 스위치 여부에 상관없이 rc522의 led가 항상 점등된다...

 

해결 : 못했다. 저항 다 끊어버리고 아날로그 input핀 2개 각각 연결해줄까..

 

 

 

2. 조도센서에 따른 네오픽셀 led 조절

네오픽셀의 brightness 함수가 어떻게 동작하는 건지 모르겠다. 조도센서를 좀 어둡게 하면 led가 갑자기 확 밝아진다. 근데 완전히 가리면 0이 되는지 밝기가 0이 되기는 한다.

해결 : 못했다.

 

 

 

 

 

 

 

 

 

 

 

 

아두이노 갖고 노는데 너무 많은 시간을 사용해버렸다.

어서 LOS 마저 풀어야지..

반응형

+ Recent posts