福井県勝山市内の山中に設置されている約60台の獣害対策用の箱罠(イノシシ用)の動作状況を把握したい。
具体的には、
「IchigoJam」と「さくらのIoT Platform β」を使用して通信機能を持つ箱罠を作成し、「Microsoft Azure」に箱罠の動作イベントを送信します。
「Microsoft Azure」からはレポート生成ツール「Power BI」への連携やメール送信を行ないます。
また、「Table Storage」にログを保存します。
箱罠に「IchigoJam」と接続された距離センサーとソレノイドを設置し、害獣が箱罠に入ったとき、とびらを閉じるとともに「さくらの通信モジュール(LTE)-β版」を経由して「さくらのIoT Platform β」とその先の「Microsoft Azure」に動作イベントを通知します。
「IchigoJam」と「さくらの通信モジュール(LTE)-β版」は、信号レベルの変換(3.3V <->1.8V)を施した上でI2Cで通信します。
IchigoJam BASIC の POKE を使用して、メモリ上に「さくらの通信モジュール(LTE)-β版」の仕様に則ったバイト列を作り、I2CWで送信します。
箱罠 |
箱罠制御装置 |
IchigoJam |
1 'INOSHISHI VER:1.2 8 C=0:N=0 9 OUT 4,-1 10 V=(ANA(8)*19/12)+70 11 D=1024-ANA(2)+C 15 ?V;" ";D 20 IF D<V N=N+1 ELSE N=0 25 IF 3<=N OUT1:WAIT30:OUT0:LED1:GOSUB10010:END 30 GOTO10 5 I=1011 6 H=#00 10010 E=#21: S=#0A: T=#49 10020 L = I % #100 10030 M = I / #100 10040 P= E ^ S ^ H ^ T ^ L ^ M 10050 POKE #700,E,S,H,T,L,M,#00,#00,#00,#00,#00,#00,P 10060 R=I2CW(#4F,#700,1,#701,12) 10070 RETURN
箱罠から送信された動作イベントは、「IoT Hub」に格納されます。
「Stream Analytics」に設定したクエリがこの「IoT Hub」を常に監視しており、吸い上げた動作イベントをレポート生成ツール「Power BI」と、管理者にメールを送信するために設置した「Event Hub」に転送します。
また、「Function App」で作成したアプリケーションが「Event Hub」を常に監視しており、吸い上げた動作イベントからメールを作成し、「SendGrid」に渡すことでメールが送信されます。
#r "Newtonsoft.Json" using System.Net; using Microsoft.Azure.Devices.Client; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Text; public static async Task Run(HttpRequestMessage req, TraceWriter log) { string postData = await req.Content.ReadAsStringAsync(); dynamic json = JsonConvert.DeserializeObject<dynamic>(postData); string deviceId; try { deviceId = json.payload.channels[0].value; }catch(Exception ex){ // device status message // do nothing return; } var connStr = Environment.GetEnvironmentVariable("IOTHUB_BROWSER_CONNSTR"); var manager = Microsoft.Azure.Devices.RegistryManager.CreateFromConnectionString(connStr); var device = await manager.GetDeviceAsync(deviceId); if (device != null) { var twin = await manager.GetTwinAsync(deviceId); double la = 0.0; double lo = 0.0; if(twin.Tags.Contains("naturalstyle")) { dynamic props = twin.Tags["naturalstyle"]; la = props.location.latitude; lo = props.location.longitude; } log.Info($"la:{la},lo:{lo}"); var ns = new { location = new { latitude = la, longitude = lo } }; json.naturalstyle = JToken.FromObject(ns); string uri = Environment.GetEnvironmentVariable("IOTHUB_URI"); string deviceConnStr = "HostName=" + uri + ";DeviceId=" + deviceId + ";SharedAccessKey=" + device.Authentication.SymmetricKey.PrimaryKey; var client = DeviceClient.CreateFromConnectionString(deviceConnStr); await client.OpenAsync(); await client.SendEventAsync(new Message(Encoding.UTF8.GetBytes(json.ToString()))); await client.CloseAsync(); } }
WITH temp AS ( SELECT GetRecordPropertyValue(GetArrayElement(payload.channels,0),'value') AS cageid, DATEADD(hour,9,GetRecordPropertyValue(GetArrayElement(payload.channels,0),'datetime')) AS eventdt, naturalstyle.location.latitude AS latitude, naturalstyle.location.longitude AS longitude FROM fromIotHub ), events AS ( SELECT cageid, eventdt, latitude, longitude, DATETIMEFROMPARTS(YEAR(eventdt),MONTH(eventdt),DAY(eventdt),0,0,0,0) AS eventdate, DATEPART(hour,eventdt) AS eventhour FROM temp ) SELECT * INTO toPowerBI FROM events SELECT * INTO toSendGrid FROM events SELECT * INTO toTableStorage FROM events
#r "Newtonsoft.Json" #r "SendGrid" using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SendGrid.Helpers.Mail; const string mailTo = "admin@example.com"; public static Mail Run(string message, TraceWriter log) { log.Info($"message: {message}"); dynamic json = JsonConvert.DeserializeObject<object>(message); // JSONから必要なパラメータを取り出す int numb = json.cageid; DateTime ltime = json.eventdt.ToObject<DateTime>(); string time = ltime.ToString("yyyy/MM/dd HH:mm:ss"); // 日本風フォーマット double la = json.latitude; double lo = json.longitude; // メール作成 string subject = $"[箱罠監視] 箱罠:{numb} が閉じました!"; string mapurl = "http://maps.google.com/maps"; string body = $"箱罠が閉じました!\n箱罠番号: {numb}\n日時: {time}\n場所: {mapurl}?q={la},{lo}"; log.Info(subject); log.Info(body); var mail = new Mail(null, subject, new Email(mailTo), new Content("text/plain", body)); mail.TrackingSettings = NewTrackingSettings(); return mail; } public static TrackingSettings NewTrackingSettings() { TrackingSettings trackingSettings = new TrackingSettings(); ClickTracking clickTracking = new ClickTracking(); clickTracking.Enable = false; clickTracking.EnableText = false; trackingSettings.ClickTracking = clickTracking; return trackingSettings; }