Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
IoT推進ラボ キャッチアップ
Search
rpaka
October 24, 2018
Programming
0
1.1k
IoT推進ラボ キャッチアップ
学内での知見共有用に作成した資料です。
This is presentation material to share my knowledge about IoT system.
rpaka
October 24, 2018
Tweet
Share
More Decks by rpaka
See All by rpaka
Driver Authentication for Smart Car Using Wireless Sensing
ritsu2891
0
890
情報家電とネットワーク
ritsu2891
0
1.2k
エネルギーの情報化 -電力のパケット化とルーティング技術-
ritsu2891
0
1.4k
スマートゴミ管理システム
ritsu2891
0
1.3k
The Channel as a Traffic Sensor: Vehicle Detection and Classification Based on Radio Fingerprinting
ritsu2891
0
1.3k
A Little Java, a Few Patterns -Ch.7 Oh, My!-
ritsu2891
0
1.2k
ARSを⽤いたFM-CWレーダーの距離分解能改善に関する検討
ritsu2891
0
1.6k
ARSを⽤いた信号分離性能に関する検討
ritsu2891
0
1.3k
Sensor Fusion for Unobtrusive Respiratory Rate Estimation in Dogs
ritsu2891
0
1.6k
Other Decks in Programming
See All in Programming
オープンソースソフトウェアへの解像度🔬
utam0k
17
3.2k
技術的負債の正体を知って向き合う
irof
0
290
社会人になっても趣味開発を続けたい! / traPavilion
mazrean
1
110
pnpm に provenance のダウングレード を検出する PR を出してみた
ryo_manba
1
160
他言語経験者が Golangci-lint を最初のコーディングメンターにした話 / How Golangci-lint Became My First Coding Mentor: A Story from a Polyglot Programmer
uma31
0
470
テーブル定義書の構造化抽出して、生成AIでDWH分析を試してみた / devio2025tokyo
kasacchiful
0
320
NixOS + Kubernetesで構築する自宅サーバーのすべて
ichi_h3
0
1.2k
AI Agent 時代的開發者生存指南
eddie
4
2.2k
Pythonに漸進的に型をつける
nealle
1
140
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
360
なんでRustの環境構築してないのにRust製のツールが動くの? / Why Do Rust-Based Tools Run Without a Rust Environment?
ssssota
14
47k
スマホから Youtube Shortsを見られないようにする
lemolatoon
27
34k
Featured
See All Featured
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
658
61k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
640
Product Roadmaps are Hard
iamctodd
PRO
55
11k
Statistics for Hackers
jakevdp
799
220k
Building an army of robots
kneath
306
46k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.1k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
A designer walks into a library…
pauljervisheath
209
24k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
Side Projects
sachag
455
43k
Scaling GitHub
holman
463
140k
Transcript
キャッチアップ IoT推進研 学⽣チーム 2018/10/24 ⼩久保 律樹 愛知県⽴⼤学 情報科学部情報科学科
⽬次 ༰ Ø શମతͳߏ Ø Թηϯα͔Βͷσʔλͷऔಘ Ø 3BTQCFSSZ1Jͷ(1*0ϐϯ Ø *$σόΠεͱͷ௨৴
Ø -JOVYͰͷσόΠεͱͷ௨৴ Ø .Z42-ͷॻ͖ࠐΈ Ø %#͔Βͷσʔλͷऔಘ Ø ϧʔςΟϯά Ø 8FCαʔόͷಇ͖ Ø ඇಉظ௨৴ Ø +40/ܗࣜ Ø -BSBWFM Ø άϥϑͷදࣔ Ø "+"9 Ø $IBSUKT Ø μετωοτͷར༻ Ø ߏҊ Ø Ϟʔτ ϥζύΠͷଓ Ø Ϛωʔδϟ 1$ͷଓ Ø 4.24-ɾ4.4%,ͷར༻ Ø ࢀߟࢿྉͷఏڙ
はじめに ࣭ਵ࣌Ͳ͏ͧ ͜ͷࢿྉ͠·͢ ͜ͷߏ͚͕ͩਖ਼͍͠Θ͚Ͱͳ͍ • ͬͱྑ͍ํ๏͕͋Δ͔ • օͰߟ͍͖͑ͯ·͠ΐ͏
全体的な構成
何をしたいか 1$ 3BTQCFSSZ1J Թηϯα
⼤雑把に⽅式を決定(1) 1$ 8&#αʔό͔Βσʔλऔಘ άϥϑนը ϒϥβ 8&#αʔό %#͔Βσʔλऔಘ σʔλͷՃ 3BTQCFSSZ1J
%# ϓϩάϥϜ ηϯα͔Βσʔλऔಘ σʔλͷՃ %#ͷॻ͖ࠐΈ
⼤雑把に⽅式を決定(2) 1$ 3BTQCFSSZ1J ϒϥβ 8&#αʔό 8&#αʔόͷೖΓޱ σʔλϕʔε ϓϩάϥϜ Թηϯα
ϓϩάϥϜ ϓϩάϥϜ σʔλͷऔಘɾՃ σʔλͷอଘ σʔλͷऔಘɾՃ σʔλͷදࣔ
具体的に何を使うのか 1$ 3BTQCFSSZ1J ϒϥβ $IBSUKT άϥϑ੍ޚ +4 8&#αʔό /HJOY
-BSBWFM .Z42- ηϯα੍ޚ $1ZUIPO %#σʔλऔಘ QIQ Թηϯα
温度センサからの データの取得
何をするプログラムなのか Թηϯα σʔλϕʔε
処理の流れ 3BTQCFSSZ1J .Z42- Թηϯα ηϯα੍ޚ $1ZUIPO Թηϯαʹଓ ίϚϯυൃߦ
̍ σʔλΛՃ ˠ ઁࢯ ̎ .Z42-ʹॻ͖ࠐΈ ̏
1. 温度センサに接続・コマンド発⾏ 3BTQCFSSZ1Jͷ(1*0ϐϯ (1*0ϐϯ ୯७ͳ0/0'' -&%ͷ౮ σΟδλϧ௨৴ ηϯαͷར༻ ֎෦ػثͱͷ࿈ܞ
1. 温度センサに接続・コマンド発⾏ *$ʹΑΔ௨৴ ϥζύΠ ηϯα ηϯα ηϯα Y Y
Y Ϩδελ Ϩδελ Y Y ෳͷηϯαΛଓ͠ɼΞυϨεͰ۠ผ ηϯα෦ͷϨδελΛΞυϨεͰ۠ผ ʢ͢Δ߹͋Δʣ ͋͘·Ͱ௨৴ํࣜ σʔλͷܗࣜ௨৴ͷ༰ ηϯαʔͷ༷ʹΑΔ
1. 温度センサに接続・コマンド発⾏ *$σόΠε͔Βͷσʔλऔಘʢ̍ʣ ϓϩάϥϜ read() σόΠεϑΝΠϧ *D ʁ ͍͖ͳΓಡ·ΕͯԿΛฦͨ͠Βྑ͍͔͔Βͳ͍
1. 温度センサに接続・コマンド発⾏ *$σόΠε͔Βͷσʔλऔಘʢ̎ʣ ϓϩάϥϜ write() σόΠεϑΝΠϧ *D ίϚϯυΛൃߦͯ͠σʔλऔಘ read()
ԹσʔλΛଌͬͯԼ͍͞
1. 温度センサに接続・コマンド発⾏ -JOVYͰͷσόΠεͱͷ௨৴ 595ϑΝΠϧ 'PPUYU σόΠεϑΝΠϧ *D
Χʔωϧ 1. 温度センサに接続・コマンド発⾏ -JOVYͷσόΠευϥΠό ϓϩάϥϜ σόΠευϥΠό read() σόΠευϥΠό read()
write() σόΠεϑΝΠϧ *D ioctl() σόΠεಛ༗ ͷૢ࡞ σόΠευϥΠό
2. データを加⼯ / 3. MySQLに書き込み ̎ʹ͍ͭͯԹηϯαʹ͍༷ͭͯʹैͬͯΛՃ͍ͯ͠Δ͚ͩ ̏ʹ͍ͭͯ.Z42-$POOFDUPSͱ͍͏ެࣜϥΠϒϥϦΛར༻ • ৭ʑͳݴޠͷόʔδϣϯ͕ଘࡏ
• ແྉͰར༻Մೳ
3. MySQLに書き込み sql::Driver *driver; sql::Connection *con; sql::Statement *stmt; sql::PreparedStatement
*p_stmt; driver = get_driver_instance(); con = driver->connect("tcp://127.0.0.1:3306", "ritsu2891", "****"); stmt = con->createStatement(); stmt->execute("USE iot_dev;"); p_stmt = con->prepareStatement("INSERT INTO temp (`data`, `timestamp`) VALUES (?, ?);"); p_stmt->setDouble(1, sht31.readTemp()); p_stmt->setString(2, "00:00:00"); p_stmt->execute(); $ 42-จ
DBからの データの取得
何をするプログラムなのか σʔλϕʔε ϒϥβ
処理の流れ 1$ 8&#αʔό -BSBWFM .Z42- %#σʔλऔಘ QIQ 3BTQCFSSZ1J
%#͔Βσʔλऔಘ ̍ +40/ܗࣜͰแΉ ̎ )5.-$44+4ϑΝΠϧ ϒϥβ %#σʔλͷཁٻԠ άϥϑนըϓϩάϥϜͷ৴
ルーティング IPNF CMPH TQFDJBM UFNQ UFNQBMM ϒϥβ τοϓΛ දࣔ͢Δ
ϩάΠϯϢʔβ ͷೝূ ԹใΛ औಘ͢Δ ϒϩάهࣄΛ දࣔ͢Δ ϓϩάϥϜ ॲཧͷબ ʢϧʔςΟϯάʣ 8&#αʔό
Webサーバの働き(1) ϒϥβ <!doctype html> <html lang="ja"> <head> <meta charset="UTF-8">
<meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no- cache"> <meta name="viewport" content="width=device- width,initial-scale=1.0"> <meta name="format-detection" content="telephone=no"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <link href="css/index.css" rel="stylesheet" type="text/css"> <link href="css/index_sp.css" rel="stylesheet" type="text/css" class="sp_view"> <meta name="Keywords" content="愛知県⽴⼤学, Aichi Prefectural University, 県⼤, 名古屋, ⻑久⼿, 守⼭, APU"> <meta name="Description" content="愛知県⽴⼤学公式サイ トです。5学部10学科、⼤学院4研究科を擁する総合⼤学。⼤学の紹介 や⼊試情報、学部・⼤学院、就職・キャリア、学⽣⽣活、教育情報の 公表などの情報を掲載しています。"> <title>愛知県⽴⼤学</title> 8FCαʔό ʮJOEFYIUNMʯͷ ϖʔδΛԼ͍͞ɻ 0,Ͱ͢ɻ༰ʮŋŋŋ ݁ہɺจࣈྻΛฦͯ͠Δ͚ͩ *OEFYIUNM ༰ΛௐΔ ղऍ
Webサーバの働き(2) ϒϥβ 8FCαʔό ʮEBUBʯ ͷϖʔδΛԼ͍͞ɻ 0,Ͱ͢ɻ༰ʮŋŋŋ ͲΜͳจࣈྻͰྑ͍ 'PP #BB
'PP #BB
⾮同期通信(1) ϒϥβ 8FCαʔό άϥϑશମͦͷͷΛมԽ͢ΔʹૹΔʁ ŋŋŋ ϖʔδશମ͕ॻ͖ΘΔ ˠ ϖʔδ͕ͪΒͭ͘ ˠ
ແବͳ௨৴͕ൃੜ
⾮同期通信(2) ϒϥβ 8FCαʔό ৽͍͠ॴ͚ͩॻ͖͑Δ ŋŋŋ ৽͍͠σʔλ͚ͩཪͰऔಘ
ˠϖʔδͷҰ෦ͷΈॻ͖͑ ˠॻ͖ΘΔ෦͚ͩนը
JSON形式 +BWB4DSJQU 0CKFDU/PUBUJPO { "type" : "Temperature", "from" :
"mote", "mac-addr” : "0x01", "inner-item" : { "child1" : "Jane Smith", "child2" : "123 Maple Street" }, "data" : 24.5, "timestamp” : "2018-10-21 21:12:41 JST" } 1)1 +4 $ 1ZUIPO +BWB • +4ͷΦϒδΣΫτͷจࣈදݱ • ܰྔͳσʔλ • ѻ͍͍͢ɿ৭ʑͳڥͰར༻Մ • ਓͷʹݟ͍͢ • 8&#"1*ͰΑ͘ར༻͞ΕΔ +40/
Laravelとは • 1)1ͷ8&#ϑϨʔϜϫʔΫ • ϑϧελοΫʢػೳϞϦϞϦʣ • .7$ • ಡΈ͍͢ɺॻ͖͍͢ʢͱݴΘΕΔʣ
• ಉҙͰ͖ΔʢൺֱతಡΈॻ͖͍͢͠ͱࢥ͏ʣ • υΩϡϝϯτ͕๛ʢຊޠ͋Γʣ • ྲྀߦͬͯΔʢωοτ্ʹใຬࡌʣ • %*ʢґଘੑೖʣ • ϑΝαʔυ • σϑΥϧτͰ"NB[PO4ʹଓ • 7VFKTͱͷ౷߹ ΊͪΌศར Γ͗͢ʁ ػೳϞϦϞϦ͔ͭॳ৺ऀ͖ ͏ػೳ͚ͩཧղ͢Ε0, Ͱ͖Δ͜ͱଟա͗ʂ ແྉʂ
Laravelの使⽤ ̶ ルーティング Route::get('/', function () { return view('home');
}); Route::get('/temp/all', "TempController@all"); Route::get('/temp/new/{id}', 'TempController@new'); 1)1 ϒϥβ BMM UFNQBMM UFNQOFX\JE^ OFX JE 5FNQ$POUSPMMFS )PNFCMBEFQIQ )5.-Έ͍ͨͳͭ
Laravelの使⽤ ̶ DBアクセス・JSONで包む namespace App¥Http¥Controllers; use Illuminate¥Support¥Facades¥DB; class TempController
{ public function all() { $data = DB::table('temp')->get(); // SQL: SELECT * FROM temp; return response()->json($data); } public function new($id) { $data = DB::table('temp')->where('id', '>', $id)->get(); // SQL: SELECT * FROM temp WHERE id > $id; return response()->json($data); } } 1)1 நԽ͞Εͨ%#ΞΫηε 42-จΛΒͳͯ͘ྑ͍ +40/ܗࣜͷมҰൃ %# ྻ +40/ ϒϥβ
グラフの表⽰
何をするプログラムなのか σʔλϕʔε ϒϥβ σʔλ )5.-$BOWBT
処理の流れ 1$ ϒϥβ $IBSUKT άϥϑ੍ޚ +4 8&#αʔό /HJOY
8&#αʔό͔Β σʔλऔಘ ̍ άϥϑนը ̎ +40/ܗࣜ グラフ壁画ライブラリ
⾮同期通信(AJAX) var updateData = function () {$.ajax({ url :
"/temp/new/" + id, type : "GET", async : true, data : null, dataType: "json", success : function(result) { console.log(result); Object.keys(result).forEach(function(key) { label.push(' ‘); temp.push(result[key].data); id = result[key].id; c.update(); }); } });} window.setInterval(updateData, 5 * 1000); +4 8&#αʔό UFNQOFX\JE^ +40/ σʔλ σʔλ σʔλ
グラフ壁画ライブラリ ̶ 無料でこのクオリティはやばいよ2
グラフ壁画ライブラリ ̶ ほぼ何もしなくて良い var drawGraph = function(label, temp){ var
ctx = document.getElementById('graph').getContext('2d’); var myChart = new Chart(ctx, { type: 'line’, data: { labels: label, datasets: [{ label:'気温', data:temp }] } }); return myChart; }; window.onload=function () { var label = [’’]; var temp = []; var last_id = -1; c = drawGraph(label, temp); } c.update(); +4 UFNQʹσʔλΛՃͯ͠ VQEBUF Λ࣮ߦ͢Δ͚ͩ ৭ʑͳઃఆ
ダストネットの利⽤
説明した構成 1$ 3BTQCFSSZ1J ϒϥβ $IBSUKT άϥϑ੍ޚ +4 8&#αʔό
/HJOY -BSBWFM .Z42- ηϯα੍ޚ $1ZUIPO %#σʔλऔಘ QIQ Թηϯα 8J'J
ダストネットでそのまま置き換える?(1) 1$ 3BTQCFSSZ1J ϒϥβ $IBSUKT άϥϑ੍ޚ +4 8&#αʔό
/HJOY -BSBWFM .Z42- ηϯα੍ޚ $1ZUIPO %#σʔλऔಘ QIQ Թηϯα
ダストネットでそのまま置き換える?(2) ηϯα ηϯα੍ޚ μετωοτ௨৴੍ޚ 1$ αʔό Ϟʔτ Ϛωʔδϟ 3BTQCFSSZ1J
μετωοτ௨৴੍ޚ /HJOY 8&#αʔό -BSBWFM %#σʔλऔಘ ϒϥβ $IBSUKT άϥϑ੍ޚ Ϟʔτ Ϟʔτ .Z42-
ダストネットを導⼊した構成案 ηϯα ηϯα੍ޚ μετωοτ௨৴੍ޚ 1$ αʔό Ϟʔτ Ϛωʔδϟ 3BTQCFSSZ1J
μετωοτ௨৴੍ޚ /HJOY 8&#αʔό -BSBWFM %#σʔλऔಘ ϒϥβ $IBSUKT άϥϑ੍ޚ όοϑΝ 595ϑΝΠϧͳͲ Ϟʔτ .Z42- Ϟʔτ
ダストネットのモートとRaspberry Piの接続(1) 3BTQCFSSZ1J Ϟʔτ γϦΞϧ௨৴ 6"35
ダストネットのモートとRaspberry Piの接続(2) 3BTQCFSSZ1J Ϟʔτ
γϦΞϧ௨৴ σόΠευϥΠό ダストネットでの通信 ̶ モート側 3BTQCFSSZ1J Ϟʔτ $ϓϩάϥϜ ʢࣗͷϓϩάϥϜʣ
4NBSU.FTI 2VJDL4UBSU-JCSBSZ 4NBSU.FTI $-JCSBSZ μετωοτ ϑΝʔϜΣΞ • Ϟʔτͷ௨৴ঢ়ଶΛཧ͢ Δঢ়ଶભҠػց • ͱΓ͋͑ͣ͏༻ͷ؆ศͳ "1*ͷఏڙ • ϥζύΠ༻ͷϓϩάϥϜย ʢԼҐͷ$ϥΠϒϥϦͰ ΘΕΔʣ • "1*Λୟ͚ͩ͘ • ௨৴ʹؔ͢ΔԼҐͷॲཧ ʢ04*ࢀরϞσϧͷωοτ ϫʔΫҎԼʹ֘͢Δॲ ཧʣؾʹ͠ͳͯ͘ྑ͍
SmartMesh QSL サンプルコード ̶ マネージャへの送信 uint8_t payload[4]; uint8_t inboxBuf[DN_DEFAULT_PAYLOAD_SIZE_LIMIT];
uint8_t bytesRead; dn_qsl_init(); // Always returns TRUE at the moment while (TRUE) { if (dn_qsl_isConnected()) { static uint8_t count = 0; dn_write_uint32_t(payload, val); if (dn_qsl_send(payload, sizeof (payload), DEST_PORT)) {} else {} do { bytesRead = dn_qsl_read(inboxBuf); parsePayload(inboxBuf, bytesRead); } while (bytesRead > 0); dn_sleep_ms(DATA_PERIOD_MS); } else { if (dn_qsl_connect(NETID, JOINKEY, SRC_PORT, BANDWIDTH_MS)) {} else {} } } $
ダストネットのマネージャとPCの接続 Ϛωʔδϟ 64# ʢγϦΞϧʣ 1$
γϦΞϧ௨৴ σόΠευϥΠό ダストネットでの通信 ̶ マネージャ側 Ϛωʔδϟ 1ZUIPOϓϩάϥϜ ʢࣗͷϓϩάϥϜʣ 4NBSU.FTI
4%, QZ4FSJBM μετωοτ ϑΝʔϜΣΞ • "1*Λୟ͚ͩ͘ • 1ZUIPO༻ϥΠϒϥϦ • ʮ௨ʯͷड৴༻Ϋϥε͕ ༻ҙ͞ΕͯΔͳͲɺ͔ͳΓ ߴϨϕϧͳॴ·Ͱ࡞ΒΕͯ Δ • ֤छπʔϧྨʢ8JOEPXT ༻ʣଐ • 04ͷγϦΞϧ௨৴ͷৄࡉ ΛӅṭʁ • 8JOͰ.BDͰ-JOVYͰ ͑ͨ 1$
SmartMesh SDK サンプルコード ̶ 通知の取得 connector = IpMgrConnectorSerial.IpMgrConnectorSerial() connector.connect({'port':
'/dev/tty.usbserial-00001014D’}) notif_client_hndl = NotifClient.NotifClient(connector, None) class NotifClient(object): def __init__(self, connector, disconnected_callback): self.connector = connector self.subscriber = IpMgrSubscribe.IpMgrSubscribe(self.connector) self.subscriber.start() self.subscriber.subscribe( notifTypes=[ IpMgrSubscribe.IpMgrSubscribe.NOTIFDATA, IpMgrSubscribe.IpMgrSubscribe.NOTIFIPDATA, ], fun=self._notif_callback, isRlbl=False, ) def _notif_callback(self, notif_name, notif_params): 1ZUIPO
END