source: asp3_tinet_ecnl_arm/trunk/app3_human_detec/src/echonet_main.c@ 364

Last change on this file since 364 was 364, checked in by coas-nagasima, 5 years ago

TINETとSocket APIなどを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 15.5 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014-2018 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37
38/*
39 * サンプルプログラム(1)の本体
40 */
41
42#include <kernel.h>
43#include <t_syslog.h>
44#include <t_stdlib.h>
45#include <sil.h>
46#include <string.h>
47#include "syssvc/serial.h"
48#include "syssvc/syslog.h"
49#include "kernel_cfg.h"
50#include "echonet_main.h"
51#include "echonet_cfg.h"
52#include "target_kernel_impl.h"
53#include "gpio_api.h"
54#include "analogin_api.h"
55
56/* TODO: メーカーコードを設定 */
57#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
58
59/* ノードプロファイルオブジェクト */
60struct ecn_cls0EF0_t node_profile_data = {
61 0x30, /* 動作状態 */
62 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
63 {
64 0xFE, /* 下位通信層IDフィールド */
65 { MAKER_CODE }, /* メーカーコード */
66 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
67 },
68 0x0000, /* 異常内容 */
69 { MAKER_CODE }, /* メーカーコード */
70};
71
72/* 人体検知センサクラス */
73struct ecn_cls0007_t human_detection_sensor_data = {
74 0x30, /* 動作状態 */
75 0x35, /* 検知閾値レベル設定(初期値として1~4が未検出、初期値として4~8が検出) */
76 0x31, /* 検知レベル状態(人体検知状態用)*/
77 0x00, /* 設置場所 */
78 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
79 0x42, /* 異常発生状態 */
80 { MAKER_CODE }, /* メーカーコード */
81};
82
83/* 電源LED */
84gpio_t pow_led;
85/* カラーLED */
86gpio_t led_blue, led_green, led_red;
87/* ユーザースイッチ CN16-4 */
88gpio_t sw1, sw2;
89
90/*
91 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
92 */
93int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
94{
95 /* サイズが1以外は受け付けない */
96 if (size != 1)
97 return 0;
98
99 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
100
101 switch (*(uint8_t *)src) {
102 /* ONの場合 */
103 case 0x30:
104 *((uint8_t *)item->exinf) = *((uint8_t *)src);
105 /* LEDをON */
106 gpio_write(&pow_led, 1);
107 break;
108 /* OFFの場合 */
109 case 0x31:
110 *((uint8_t *)item->exinf) = *((uint8_t *)src);
111 /* LEDをOFF */
112 gpio_write(&pow_led, 0);
113 break;
114 /* 0x30か0x31以外は受け付けない */
115 default:
116 return 0;
117 }
118
119 return 1;
120}
121
122/*
123 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
124 */
125int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
126{
127 /* サイズが1以外は受け付けない */
128 if (size != 1)
129 return 0;
130
131 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
132
133 switch (*(uint8_t *)src) {
134 /* 異常発生ありの場合 */
135 case 0x41:
136 /* 異常発生なしの場合 */
137 case 0x42:
138 *((uint8_t *)item->exinf) = *((uint8_t *)src);
139 break;
140 /* 0x41か0x42以外は受け付けない */
141 default:
142 return 0;
143 }
144
145 return 1;
146}
147
148/*
149 * 検知閾値レベル設定設定関数
150 */
151int detection_threshold_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
152{
153 /* サイズが1以外は受け付けない */
154 if (size != 1)
155 return 0;
156
157 if ((*(uint8_t *)src >= 0x31) && (*(uint8_t *)src <= 0x38)) {
158 *((uint8_t *)item->exinf) = *((uint8_t *)src);
159 }
160 /* 上記以外は受け付けない */
161 else {
162 return 0;
163 }
164
165 return 1;
166}
167
168uint8_t led_disp[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
169
170/*
171 * 検知レベル設定関数
172 */
173int detection_state_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
174{
175 struct ecn_cls0007_t *eobj = (struct ecn_cls0007_t *)item->exinf;
176 ER ret;
177 T_EDATA *esv;
178 uint8_t prev_state;
179 int temp;
180
181 /* サイズが1以外は受け付けない */
182 if (size != 1)
183 return 0;
184
185 *anno = false;
186
187 if ((*(uint8_t *)src >= 0x31) && (*(uint8_t *)src <= 0x38)) {
188 /* 以前の検知レベルを保存 */
189 prev_state = eobj->state;
190 /* 検知レベル設定 */
191 eobj->state = *((uint8_t *)src);
192 /* LEDに検知レベルを表示 */
193 temp = led_disp[eobj->state - 0x30];
194 gpio_write(&led_blue, (temp & 0x01) != 0 ? 1 : 0);
195 gpio_write(&led_green, (temp & 0x02) != 0 ? 1 : 0);
196 gpio_write(&led_red, (temp & 0x04) != 0 ? 1 : 0);
197
198 /* 人体検知状態に変化があった場合 */
199 if ((prev_state < eobj->threshold) != (eobj->state < eobj->threshold)) {
200 /* プロパティ通知 */
201 *anno = true;
202 }
203 }
204 /* 上記以外は受け付けない */
205 else {
206 return 0;
207 }
208
209 return 1;
210}
211
212/*
213 * 人体検知状態取得関数
214 */
215int detection_state_get(const EPRPINIB *item, void *dst, int size)
216{
217 struct ecn_cls0007_t *eobj = (struct ecn_cls0007_t *)item->exinf;
218
219 /* 閾値より検知レベルが低い場合 */
220 if (eobj->state < eobj->threshold) {
221 /* 人体検知なし */
222 ((uint8_t *)dst)[0] = 0x42;
223 }
224 /* 閾値より検知レベルが高い場合 */
225 else {
226 /* 人体検知あり */
227 ((uint8_t *)dst)[0] = 0x41;
228 }
229
230 return 1;
231}
232
233static void main_initialize();
234static int main_get_timer();
235static void main_progress(int interval);
236static void main_recv_esv(T_EDATA *esv);
237static void main_break_wait(uint8_t *brkdat, int32_t len);
238static void main_timeout();
239
240/*
241 * メインタスク
242 */
243void echonet_main_task(intptr_t exinf)
244{
245 ER ret, ret2;
246 SYSTIM prev, now;
247 int timer;
248 T_EDATA *esv;
249 uint8_t brkdat[64];
250 int32_t len;
251
252 /* アプリケーションの初期化 */
253 main_initialize();
254
255 ret2 = get_tim(&now);
256 if (ret2 != E_OK) {
257 syslog(LOG_ERROR, "get_tim");
258 return;
259 }
260
261 for (;;) {
262 prev = now;
263
264 /* タイマー取得 */
265 timer = main_get_timer();
266
267 /* 応答電文待ち */
268 ret = ecn_trcv_esv(&esv, timer);
269 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)) {
270 syslog(LOG_ERROR, "ecn_trcv_esv");
271 break;
272 }
273
274 ret2 = get_tim(&now);
275 if (ret2 != E_OK) {
276 syslog(LOG_ERROR, "get_tim");
277 break;
278 }
279
280 /* 時間経過 */
281 main_progress(now - prev);
282
283 /* Echonet電文受信の場合 */
284 if (ret == E_OK) {
285 /* Echonet電文受信処理 */
286 main_recv_esv(esv);
287
288 /* 領域解放 */
289 ret = ecn_rel_esv(esv);
290 if (ret != E_OK) {
291 syslog(LOG_ERROR, "ecn_rel_esv");
292 break;
293 }
294 }
295 /* 応答電文待ちの割り込みの場合 */
296 else if (ret == E_BRK) {
297 /* 応答電文待ちの割り込みデータ取得 */
298 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
299 if (ret != E_OK) {
300 syslog(LOG_ERROR, "ecn_get_brk_dat");
301 break;
302 }
303
304 /* 応答電文待ちの割り込み処理 */
305 main_break_wait(brkdat, len);
306
307 /* 領域解放 */
308 ret = ecn_rel_esv(esv);
309 if (ret != E_OK) {
310 syslog(LOG_ERROR, "ecn_rel_esv");
311 break;
312 }
313 }
314
315 /* タイムアウト処理 */
316 main_timeout();
317 }
318}
319
320void echonet_change_netif_link(uint8_t link_up, uint8_t up)
321{
322 ER ret;
323
324 if (link_up == 0)
325 return;
326
327 if (up) {
328 /* インスタンスリスト通知の送信 */
329 ret = ecn_ntf_inl();
330 if (ret != E_OK) {
331 syslog(LOG_ERROR, "ecn_ntf_inl");
332 }
333 }
334
335 /* メインタスクに通知 */
336 uint8_t data[2];
337 data[0] = 0x01;
338 data[1] = up ? 0x01 : 0x02;
339 ret = ecn_brk_wai(data, sizeof(data));
340 if (ret != E_OK) {
341 syslog(LOG_ERROR, "ecn_brk_wai");
342 return;
343 }
344}
345
346enum main_state_t {
347 main_state_start,
348 main_state_idle,
349};
350
351int main_timer = TMO_FEVR;
352enum main_state_t main_state = main_state_start;
353bool_t main_btn1_state;
354int main_btn1_count = 0;
355bool_t main_btn2_state;
356int main_btn2_count = 0;
357
358analogin_t analogin;
359
360/*
361 * 初期化
362 */
363static void main_initialize()
364{
365 uint8_t btn1, btn2;
366
367 /* LEDの初期化 */
368 gpio_init_out(&pow_led, LED_USER);
369 gpio_init_out(&led_blue, LED_BLUE);
370 gpio_init_out(&led_green, LED_GREEN);
371 gpio_init_out(&led_red, LED_RED);
372
373 /* スイッチの初期化 */
374 gpio_init_in(&sw1, USER_BUTTON0);
375 gpio_init_in(&sw2, P1_12);
376
377 /* カラーLEDを消灯 */
378 gpio_write(&led_blue, 0);
379 gpio_write(&led_green, 0);
380 gpio_write(&led_red, 0);
381
382 /* ECHONETミドルウェアを起動するのを待つ */
383 main_state = main_state_start;
384 main_timer = 1000 * 1000;
385
386 /* アナログ入力の初期化 */
387 analogin_init(&analogin, A0);
388
389 /* ボタン状態読み込み */
390 btn1 = gpio_read(&sw1);
391 btn2 = gpio_read(&sw2);
392 main_btn1_state = btn1 != 0;
393 main_btn2_state = btn2 != 0;
394
395 /* メインタスクを起動 */
396 ER ret = act_tsk(MAIN_TASK);
397 if (ret != E_OK) {
398 syslog(LOG_ERROR, "act_tsk");
399 }
400}
401
402/*
403 * タイマー取得
404 */
405static int main_get_timer()
406{
407 return main_timer;
408}
409
410/*
411 * 時間経過
412 */
413static void main_progress(int interval)
414{
415 if (main_timer == TMO_FEVR)
416 return;
417
418 main_timer -= interval;
419 if (main_timer < 0) {
420 main_timer = 0;
421 }
422}
423
424/*
425 * Echonet電文受信処理
426 */
427static void main_recv_esv(T_EDATA *esv)
428{
429 ER ret;
430 uint8_t epc;
431 uint8_t pdc;
432 uint8_t p_edt[256];
433 T_ENUM_EPC enm;
434
435 ret = ecn_itr_ini(&enm, esv);
436 if (ret != E_OK) {
437 syslog(LOG_ERROR, "ecn_itr_ini");
438 return;
439 }
440
441 for (;;) {
442 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
443 switch (epc) {
444 case 0x80:
445 break;
446 case 0x81:
447 break;
448 }
449 }
450 if (ret != E_BOVR) {
451 syslog(LOG_ERROR, "ecn_itr_nxt");
452 break;
453 }
454 if (enm.is_eof)
455 break;
456 }
457}
458
459/*
460 * 応答電文待ちの割り込み処理
461 */
462static void main_break_wait(uint8_t *brkdat, int32_t len)
463{
464 switch (main_state) {
465 case main_state_idle:
466 break;
467 }
468}
469
470static uint8_t main_ad_level = 1;
471static uint16_t main_ad_table[64];
472#define main_ad_table_count (sizeof(main_ad_table) / sizeof(main_ad_table[0]))
473static int main_ad_pos = 0;
474static uint32_t main_ad_avelage;
475static int main_count;
476
477static void main_ad_change();
478static void main_btn1_change(bool_t push);
479static void main_btn2_change(bool_t push);
480
481/*
482 * タイムアウト処理
483 */
484static void main_timeout()
485{
486 ER ret;
487 uint8_t btn1, btn2;
488 uint16_t ad_value;
489 uint8_t ad_level;
490
491 if (main_timer != 0)
492 return;
493
494 switch (main_state) {
495 case main_state_start:
496 /* ECHONETミドルウェアを起動 */
497 ret = ecn_sta_svc();
498 if (ret != E_OK) {
499 syslog(LOG_ERROR, "ecn_sta_svc");
500 }
501
502 /* 10ms後にボタン状態を確認 */
503 main_state = main_state_idle;
504 main_timer = 10 * 1000;
505 break;
506 case main_state_idle:
507 /* 10ms後にボタン状態を確認 */
508 main_timer = 10 * 1000;
509
510 /* ADCの変換結果取得 */
511 main_ad_avelage -= main_ad_table[main_ad_pos];
512 ad_value = analogin_read_u16(&analogin) >> 4; // 16bit値取得->12bit
513 main_ad_table[main_ad_pos] = ad_value;
514 main_ad_avelage += ad_value;
515
516 main_ad_pos++;
517 if (main_ad_pos >= main_ad_table_count) {
518 main_ad_pos = 0;
519 }
520
521 ad_level = 8 - (((main_ad_avelage / main_ad_table_count) >> 9) & 0x7);
522 if (main_ad_level != ad_level) {
523 /* 1秒変化が続いたら */
524 if (main_count < 100) {
525 main_count++;
526 }
527 else {
528 main_ad_level = ad_level;
529
530 /* ADC状態変化処理 */
531 main_ad_change();
532 }
533 }
534 else {
535 main_count = 0;
536 }
537
538 /* ボタン状態読み込み */
539 btn1 = gpio_read(&sw1);
540 btn2 = gpio_read(&sw2);
541
542 /* ボタン1の処理 */
543 if ((btn1 != 0) && !main_btn1_state) {
544 main_btn1_count++;
545 if (main_btn1_count > 10) {
546 main_btn1_count = 0;
547 main_btn1_state = true;
548
549 main_btn1_change(true);
550 }
551 }
552 else if ((btn1 == 0) && main_btn1_state) {
553 main_btn1_count++;
554 if (main_btn1_count > 10) {
555 main_btn1_count = 0;
556 main_btn1_state = false;
557
558 main_btn1_change(false);
559 }
560 }
561
562 /* ボタン2の処理 */
563 if ((btn2 != 0) && !main_btn2_state) {
564 main_btn2_count++;
565 if (main_btn2_count > 10) {
566 main_btn2_count = 0;
567 main_btn2_state = true;
568
569 main_btn2_change(true);
570 }
571 }
572 else if ((btn2 == 0) && main_btn2_state) {
573 main_btn2_count++;
574 if (main_btn2_count > 10) {
575 main_btn2_count = 0;
576 main_btn2_state = false;
577
578 main_btn2_change(false);
579 }
580 }
581 break;
582 }
583}
584
585/*
586 * ADC状態変化処理
587 */
588static void main_ad_change()
589{
590 ER ret;
591 T_EDATA *esv;
592 uint8_t p_edt[1];
593
594 p_edt[0] = 0x30 + main_ad_level;
595
596 /* プロパティ設定電文作成 */
597 ret = ecn_esv_setc(&esv, HUMAN_DETECTION_SENSOR_EOBJ, 0xB1, 1, p_edt);
598 if (ret != E_OK) {
599 syslog(LOG_ERROR, "ecn_esv_setc");
600 return;
601 }
602
603 /* 電文送信 */
604 ecn_snd_esv(esv);
605}
606
607uint8_t main_level = 1;
608bool_t main_rev = false;
609
610/*
611 * ボタン1状態変化処理
612 */
613static void main_btn1_change(bool_t push)
614{
615 ER ret;
616 T_EDATA *esv;
617 uint8_t p_edt[1];
618
619 /* 押されて戻った時に処理する */
620 if (push)
621 return;
622
623 /* 人体検知状態 */
624 if (!main_rev) {
625 main_level--;
626 if (main_level < 1) {
627 main_level = 1;
628 main_rev = true;
629 }
630 }
631 else {
632 main_level++;
633 if (main_level > 8) {
634 main_level = 8;
635 main_rev = false;
636 }
637 }
638
639 p_edt[0] = 0x30 + main_level;
640
641 /* プロパティ設定電文作成 */
642 ret = ecn_esv_setc(&esv, HUMAN_DETECTION_SENSOR_EOBJ, 0xB1, 1, p_edt);
643 if (ret != E_OK) {
644 syslog(LOG_ERROR, "ecn_esv_setc");
645 return;
646 }
647
648 /* 電文送信 */
649 ecn_snd_esv(esv);
650}
651
652/*
653 * ボタン2状態変化処理
654 */
655static void main_btn2_change(bool_t push)
656{
657 ER ret;
658 T_EDATA *esv;
659 uint8_t p_edt[1];
660
661 /* 押されて戻った時に処理する */
662 if (push)
663 return;
664
665 /* 人体検知状態 */
666 if (!main_rev) {
667 main_level++;
668 if (main_level > 8) {
669 main_level = 8;
670 main_rev = false;
671 }
672 }
673 else {
674 main_level--;
675 if (main_level < 1) {
676 main_level = 1;
677 main_rev = true;
678 }
679 }
680
681 p_edt[0] = 0x30 + main_level;
682
683 /* プロパティ設定電文作成 */
684 ret = ecn_esv_setc(&esv, HUMAN_DETECTION_SENSOR_EOBJ, 0xB1, 1, p_edt);
685 if (ret != E_OK) {
686 syslog(LOG_ERROR, "ecn_esv_setc");
687 return;
688 }
689
690 /* 電文送信 */
691 ecn_snd_esv(esv);
692}
Note: See TracBrowser for help on using the repository browser.