source: asp3_tinet_ecnl_arm/trunk/app7_buzzer/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: 14.3 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
55/* TODO: メーカーコードを設定 */
56#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
57
58/* ノードプロファイルオブジェクト */
59struct ecn_cls0EF0_t node_local_profile_data = {
60 0x30, /* 動作状態 */
61 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
62 {
63 0xFE, /* 下位通信層IDフィールド */
64 { MAKER_CODE }, /* メーカーコード */
65 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
66 },
67 { MAKER_CODE }, /* メーカーコード */
68};
69
70/* 電気ポットクラス */
71struct ecn_cls03B2_t electric_hot_water_pot_data = {
72 0x30, /* 動作状態 */
73 0x41, /* 湯切れ警告状態 */
74 0x41, /* 出湯状態 */
75 0x00, /* 設置場所 */
76 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
77 0x42, /* 異常発生状態 */
78 { MAKER_CODE }, /* メーカーコード */
79};
80
81/* ノードプロファイルオブジェクト */
82struct ecn_cls0EF0_t node_remote_profile_data = {
83 0x30, /* 動作状態 */
84 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
85 {
86 0xFE, /* 下位通信層IDフィールド */
87 { MAKER_CODE }, /* メーカーコード */
88 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
89 },
90 { MAKER_CODE }, /* メーカーコード */
91};
92
93/* ブザークラス */
94struct ecn_cls02A0_t buzzer_data = {
95 0x30, /* 動作状態 */
96 0x41, /* 音発生設定 */
97 0x00, /* 設置場所 */
98 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
99 0x42, /* 異常発生状態 */
100 { MAKER_CODE }, /* メーカーコード */
101};
102
103/* 電源LED */
104gpio_t pow_led;
105/* カラーLED */
106gpio_t led_blue, led_green, led_red;
107
108/*
109 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
110 */
111int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
112{
113 /* サイズが1以外は受け付けない */
114 if (size != 1)
115 return 0;
116
117 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
118
119 switch (*(uint8_t *)src) {
120 /* ONの場合 */
121 case 0x30:
122 *((uint8_t *)item->exinf) = *((uint8_t *)src);
123 /* LEDをON */
124 gpio_write(&pow_led, 1);
125 break;
126 /* OFFの場合 */
127 case 0x31:
128 *((uint8_t *)item->exinf) = *((uint8_t *)src);
129 /* LEDをOFF */
130 gpio_write(&pow_led, 0);
131 break;
132 /* 0x30か0x31以外は受け付けない */
133 default:
134 return 0;
135 }
136
137 return 1;
138}
139
140/*
141 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
142 */
143int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
144{
145 /* サイズが1以外は受け付けない */
146 if (size != 1)
147 return 0;
148
149 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
150
151 switch (*(uint8_t *)src) {
152 /* 異常発生ありの場合 */
153 case 0x41:
154 /* 異常発生なしの場合 */
155 case 0x42:
156 *((uint8_t *)item->exinf) = *((uint8_t *)src);
157 break;
158 /* 0x41か0x42以外は受け付けない */
159 default:
160 return 0;
161 }
162
163 return 1;
164}
165
166/*
167 * 音発生設定設定関数
168 */
169int ecn_cls02A0_propertyB1_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
170{
171 /* サイズが1以外は受け付けない */
172 if (size != 1)
173 return 0;
174
175 switch (*(uint8_t *)src) {
176 /* 音発生有の場合 */
177 case 0x41:
178 *((uint8_t *)item->exinf) = *((uint8_t *)src);
179 /* 赤LEDをON */
180 gpio_write(&led_red, 1);
181 break;
182 /* 音発生無の場合 */
183 case 0x42:
184 *((uint8_t *)item->exinf) = *((uint8_t *)src);
185 /* 赤LEDをOFF */
186 gpio_write(&led_red, 0);
187 break;
188 default:
189 /* 上記以外は受け付けない */
190 return 0;
191 }
192
193 return 1;
194}
195
196/*
197 * 湯切れ警告状態設定関数
198 */
199int no_water_warning_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
200{
201 ER ret;
202 uint8_t data[2];
203
204 /* サイズが1以外は受け付けない */
205 if (size != 1)
206 return 0;
207
208 *((uint8_t *)item->exinf) = *((uint8_t *)src);
209
210 /* メインタスクに通知 */
211 data[0] = 0x01;
212 data[1] = (*((uint8_t *)src) == 0x41) ? 0x01 : 0x00;
213 ret = ecn_brk_wai(data, sizeof(data));
214 if (ret != E_OK) {
215 syslog(LOG_ERROR, "ecn_brk_wai");
216 }
217
218 return 1;
219}
220
221/*
222 * 出湯状態設定関数
223 */
224int discharge_status_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
225{
226 ER ret;
227 uint8_t data[2];
228
229 /* サイズが1以外は受け付けない */
230 if (size != 1)
231 return 0;
232
233 *((uint8_t *)item->exinf) = *((uint8_t *)src);
234
235 /* メインタスクに通知 */
236 data[0] = 0x02;
237 data[1] = (*((uint8_t *)src) == 0x41) ? 0x01 : 0x00;
238 ret = ecn_brk_wai(data, sizeof(data));
239 if (ret != E_OK) {
240 syslog(LOG_ERROR, "ecn_brk_wai");
241 }
242
243 return 1;
244}
245
246static void main_initialize();
247static int main_get_timer();
248static void main_progress(int interval);
249static void main_recv_esv(T_EDATA *esv);
250static void main_break_wait(uint8_t *brkdat, int32_t len);
251static void main_timeout();
252
253/*
254 * メインタスク
255 */
256void echonet_main_task(intptr_t exinf)
257{
258 ER ret, ret2;
259 SYSTIM prev, now;
260 int timer;
261 T_EDATA *esv;
262 uint8_t brkdat[64];
263 int32_t len;
264
265 /* アプリケーションの初期化 */
266 main_initialize();
267
268 ret2 = get_tim(&now);
269 if (ret2 != E_OK) {
270 syslog(LOG_ERROR, "get_tim");
271 return;
272 }
273
274 for (;;) {
275 prev = now;
276
277 /* タイマー取得 */
278 timer = main_get_timer();
279
280 /* 応答電文待ち */
281 ret = ecn_trcv_esv(&esv, timer);
282 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)) {
283 syslog(LOG_ERROR, "ecn_trcv_esv");
284 break;
285 }
286
287 ret2 = get_tim(&now);
288 if (ret2 != E_OK) {
289 syslog(LOG_ERROR, "get_tim");
290 break;
291 }
292
293 /* 時間経過 */
294 main_progress(now - prev);
295
296 /* Echonet電文受信の場合 */
297 if (ret == E_OK) {
298 /* Echonet電文受信処理 */
299 main_recv_esv(esv);
300
301 /* 領域解放 */
302 ret = ecn_rel_esv(esv);
303 if (ret != E_OK) {
304 syslog(LOG_ERROR, "ecn_rel_esv");
305 break;
306 }
307 }
308 /* 応答電文待ちの割り込みの場合 */
309 else if (ret == E_BRK) {
310 /* 応答電文待ちの割り込みデータ取得 */
311 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
312 if (ret != E_OK) {
313 syslog(LOG_ERROR, "ecn_get_brk_dat");
314 break;
315 }
316
317 /* 応答電文待ちの割り込み処理 */
318 main_break_wait(brkdat, len);
319
320 /* 領域解放 */
321 ret = ecn_rel_esv(esv);
322 if (ret != E_OK) {
323 syslog(LOG_ERROR, "ecn_rel_esv");
324 break;
325 }
326 }
327
328 /* タイムアウト処理 */
329 main_timeout();
330 }
331}
332
333void echonet_change_netif_link(uint8_t link_up, uint8_t up)
334{
335 ER ret;
336
337 if (link_up == 0)
338 return;
339
340 if (up) {
341 /* インスタンスリスト通知の送信 */
342 ret = ecn_ntf_inl();
343 if (ret != E_OK) {
344 syslog(LOG_ERROR, "ecn_ntf_inl");
345 }
346 }
347
348 /* メインタスクに通知 */
349 uint8_t data[2];
350 data[0] = 0x01;
351 data[1] = up ? 0x01 : 0x02;
352 ret = ecn_brk_wai(data, sizeof(data));
353 if (ret != E_OK) {
354 syslog(LOG_ERROR, "ecn_brk_wai");
355 return;
356 }
357}
358
359enum main_state_t {
360 main_state_start,
361 main_state_idle,
362 main_state_search,
363 main_state_buzzer_on,
364};
365
366int main_timer = TMO_FEVR;
367enum main_state_t main_state = main_state_start;
368
369int main_nop_timer = TMO_FEVR;
370
371/*
372 * 初期化
373 */
374static void main_initialize()
375{
376 /* LEDの初期化 */
377 gpio_init_out(&pow_led, LED_USER);
378 gpio_init_out(&led_blue, LED_BLUE);
379 gpio_init_out(&led_green, LED_GREEN);
380 gpio_init_out(&led_red, LED_RED);
381
382 /* カラーLEDを消灯 */
383 gpio_write(&led_blue, 0);
384 gpio_write(&led_green, 0);
385 gpio_write(&led_red, 0);
386
387 /* ECHONETミドルウェアを起動するのを待つ */
388 main_state = main_state_start;
389 main_timer = 1000 * 1000;
390
391 /* メインタスクを起動 */
392 ER ret = act_tsk(MAIN_TASK);
393 if (ret != E_OK) {
394 syslog(LOG_ERROR, "act_tsk");
395 }
396}
397
398/*
399 * タイマー取得
400 */
401static int main_get_timer()
402{
403 int result = main_timer;
404
405 if ((result == TMO_FEVR)
406 || ((main_nop_timer != TMO_FEVR) && (main_nop_timer < result))) {
407 result = main_nop_timer;
408 }
409
410 return result;
411}
412
413/*
414 * 時間経過
415 */
416static void main_progress(int interval)
417{
418 if (main_timer != TMO_FEVR) {
419 main_timer -= interval;
420 if (main_timer < 0) {
421 main_timer = 0;
422 }
423 }
424
425 if (main_nop_timer != TMO_FEVR) {
426 main_nop_timer -= interval;
427 if (main_nop_timer < 0) {
428 main_nop_timer = 0;
429 }
430 }
431}
432
433/*
434 * Echonet電文受信処理
435 */
436static void main_recv_esv(T_EDATA *esv)
437{
438 ER ret;
439 ID eobjid;
440 uint8_t epc;
441 uint8_t pdc;
442 uint8_t p_edt[256];
443 T_ENUM_EPC enm;
444
445 eobjid = ecn_get_eobj(esv);
446 if (eobjid == EOBJ_NULL) {
447 syslog(LOG_ERROR, "ecn_get_eobj");
448 return;
449 }
450
451 ret = ecn_itr_ini(&enm, esv);
452 if (ret != E_OK) {
453 syslog(LOG_ERROR, "ecn_itr_ini");
454 return;
455 }
456
457 for (;;) {
458 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
459 switch (epc) {
460 case 0xD6:
461 switch (main_state) {
462 case main_state_search:
463 if (eobjid == POT_NODE_EOBJ) {
464 /* 電気ポット検索完了 */
465 main_state = main_state_idle;
466 main_timer = TMO_FEVR;
467 }
468 break;
469 }
470 break;
471 }
472 }
473 if (ret != E_BOVR) {
474 syslog(LOG_ERROR, "ecn_itr_nxt");
475 break;
476 }
477 if (enm.is_eof)
478 break;
479 }
480}
481
482static void main_buzzer_on()
483{
484 ER ret;
485 T_EDATA *esv;
486 uint8_t p_edt[1];
487
488 switch (main_state) {
489 case main_state_idle:
490 p_edt[0] = 0x41; /* 音発生有 */
491
492 /* プロパティ設定電文作成 */
493 ret = ecn_esv_seti(&esv, BUZZER_EOBJ, 0xB1, 1, p_edt);
494 if (ret != E_OK) {
495 syslog(LOG_ERROR, "ecn_esv_seti");
496 break;
497 }
498
499 /* 電文送信 */
500 ecn_snd_esv(esv);
501 if (ret != E_OK) {
502 syslog(LOG_ERROR, "ecn_snd_esv");
503 break;
504 }
505
506 main_state = main_state_buzzer_on;
507 main_timer = 1000 * 1000; /* 1秒鳴動 */
508 break;
509 case main_state_buzzer_on:
510 main_timer = 1000 * 1000; /* 1秒延長 */
511 break;
512 }
513}
514
515static void main_buzzer_off()
516{
517 ER ret;
518 T_EDATA *esv;
519 uint8_t p_edt[1];
520
521 switch (main_state) {
522 case main_state_buzzer_on:
523 p_edt[0] = 0x42; /* 音発生無 */
524
525 /* プロパティ設定電文作成 */
526 ret = ecn_esv_seti(&esv, BUZZER_EOBJ, 0xB1, 1, p_edt);
527 if (ret != E_OK) {
528 syslog(LOG_ERROR, "ecn_esv_seti");
529 break;
530 }
531
532 /* 電文送信 */
533 ecn_snd_esv(esv);
534 if (ret != E_OK) {
535 syslog(LOG_ERROR, "ecn_snd_esv");
536 break;
537 }
538
539 main_state = main_state_idle;
540 main_timer = TMO_FEVR;
541 break;
542 }
543}
544
545/*
546 * 応答電文待ちの割り込み処理
547 */
548static void main_break_wait(uint8_t *brkdat, int32_t len)
549{
550 if (brkdat[0] == 0x01) {
551 // Link up/down
552 return;
553 }
554
555 if (len < 2)
556 return;
557
558 switch (brkdat[0]) {
559 case 0x01:
560 if (brkdat[1] != 0)
561 main_buzzer_on();
562 else
563 main_buzzer_off();
564 break;
565 case 0x02:
566 if (brkdat[1] == 0)
567 main_nop_timer = 5000 * 1000; /* 5秒後にブザーON */
568 break;
569 }
570}
571
572static void main_ontimer();
573static void main_nop_timeout();
574
575/*
576 * タイムアウト処理
577 */
578static void main_timeout()
579{
580 if (main_timer == 0) {
581 main_ontimer();
582 }
583
584 if (main_nop_timer == 0) {
585 main_nop_timeout();
586 }
587}
588
589static void main_search();
590
591static void main_ontimer()
592{
593 ER ret;
594
595 switch (main_state) {
596 case main_state_start:
597 /* ECHONETミドルウェアを起動 */
598 ret = ecn_sta_svc();
599 if (ret != E_OK) {
600 syslog(LOG_ERROR, "ecn_sta_svc");
601 }
602
603 /* 1秒後にブザーを検索 */
604 main_state = main_state_search;
605 main_timer = 1000 * 1000;
606 break;
607 case main_state_search:
608 /* 電気ポット再検索 */
609 main_search();
610 main_state = main_state_search;
611 main_timer = 5000 * 1000;
612 break;
613 case main_state_buzzer_on:
614 main_buzzer_off();
615 break;
616 default:
617 main_state = main_state_idle;
618 main_timer = TMO_FEVR;
619 break;
620 }
621}
622
623static void main_search()
624{
625 ER ret;
626 T_EDATA *esv;
627
628 /* 電気ポット検索 */
629 ret = ecn_esv_inf_req(&esv, EOBJ_NULL, 0xD6);
630 if (ret != E_OK) {
631 syslog(LOG_ERROR, "ecn_esv_inf_req");
632 return;
633 }
634
635 /* 電文送信 */
636 ret = ecn_snd_esv(esv);
637 if (ret != E_OK) {
638 syslog(LOG_ERROR, "ecn_snd_esv");
639 }
640}
641
642static void main_nop_timeout()
643{
644 main_buzzer_on();
645
646 main_nop_timer = TMO_FEVR;
647}
Note: See TracBrowser for help on using the repository browser.