source: asp3_tinet_ecnl_arm/trunk/app7_buzzer/src/echonet_main.c@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 14.0 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
333bool_t started = false;
334
335void echonet_change_netif_link(uint8_t link_up, uint8_t up)
336{
337 ER ret;
338
339 if (link_up == 0)
340 return;
341
342 if (up && !started) {
343 started = true;
344
345 /* ECHONETミドルウェアを起動 */
346 ret = ecn_sta_svc();
347 if (ret != E_OK)
348 return;
349
350 /* ECHONETミドルウェアを起動するのを待つ */
351 dly_tsk(100);
352 }
353
354 /* メインタスクに通知 */
355 uint8_t data[2];
356 data[0] = 0x01;
357 data[1] = up ? 0x01 : 0x02;
358 ret = ecn_brk_wai(data, sizeof(data));
359 if (ret != E_OK) {
360 syslog(LOG_ERROR, "ecn_brk_wai");
361 return;
362 }
363}
364
365enum main_state_t{
366 main_state_idle,
367 main_state_search,
368 main_state_buzzer_on,
369};
370
371int main_timer = TMO_FEVR;
372enum main_state_t main_state = main_state_idle;
373
374int main_nop_timer = TMO_FEVR;
375
376/*
377 * 初期化
378 */
379static void main_initialize()
380{
381 /* LEDの初期化 */
382 gpio_init_out(&pow_led, LED_USER);
383 gpio_init_out(&led_blue, LED_BLUE);
384 gpio_init_out(&led_green, LED_GREEN);
385 gpio_init_out(&led_red, LED_RED);
386
387 /* カラーLEDを消灯 */
388 gpio_write(&led_blue, 0);
389 gpio_write(&led_green, 0);
390 gpio_write(&led_red, 0);
391
392 /* 1秒後にブザーを検索 */
393 main_state = main_state_search;
394 main_timer = 1000 * 1000;
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 int result = main_timer;
408
409 if((result == TMO_FEVR)
410 || ((main_nop_timer != TMO_FEVR) && (main_nop_timer < result))){
411 result = main_nop_timer;
412 }
413
414 return result;
415}
416
417/*
418 * 時間経過
419 */
420static void main_progress(int interval)
421{
422 if(main_timer != TMO_FEVR){
423 main_timer -= interval;
424 if(main_timer < 0){
425 main_timer = 0;
426 }
427 }
428
429 if(main_nop_timer != TMO_FEVR){
430 main_nop_timer -= interval;
431 if(main_nop_timer < 0){
432 main_nop_timer = 0;
433 }
434 }
435}
436
437/*
438 * Echonet電文受信処理
439 */
440static void main_recv_esv(T_EDATA *esv)
441{
442 ER ret;
443 ID eobjid;
444 uint8_t epc;
445 uint8_t pdc;
446 uint8_t p_edt[256];
447 T_ENUM_EPC enm;
448
449 eobjid = ecn_get_eobj(esv);
450 if(eobjid == EOBJ_NULL){
451 syslog(LOG_ERROR, "ecn_get_eobj");
452 return;
453 }
454
455 ret = ecn_itr_ini(&enm, esv);
456 if(ret != E_OK){
457 syslog(LOG_ERROR, "ecn_itr_ini");
458 return;
459 }
460
461 for(;;) {
462 while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
463 switch (epc) {
464 case 0xD6:
465 switch(main_state){
466 case main_state_search:
467 if (eobjid == POT_NODE_EOBJ) {
468 /* 電気ポット検索完了 */
469 main_state = main_state_idle;
470 main_timer = TMO_FEVR;
471 }
472 break;
473 }
474 break;
475 }
476 }
477 if(ret != E_BOVR){
478 syslog(LOG_ERROR, "ecn_itr_nxt");
479 break;
480 }
481 if(enm.is_eof)
482 break;
483 }
484}
485
486static void main_buzzer_on()
487{
488 ER ret;
489 T_EDATA *esv;
490 uint8_t p_edt[1];
491
492 switch(main_state){
493 case main_state_idle:
494 p_edt[0] = 0x41; /* 音発生有 */
495
496 /* プロパティ設定電文作成 */
497 ret = ecn_esv_seti(&esv, BUZZER_EOBJ, 0xB1, 1, p_edt);
498 if(ret != E_OK){
499 syslog(LOG_ERROR, "ecn_esv_seti");
500 break;
501 }
502
503 /* 電文送信 */
504 ecn_snd_esv(esv);
505 if(ret != E_OK){
506 syslog(LOG_ERROR, "ecn_snd_esv");
507 break;
508 }
509
510 main_state = main_state_buzzer_on;
511 main_timer = 1000 * 1000; /* 1秒鳴動 */
512 break;
513 case main_state_buzzer_on:
514 main_timer = 1000 * 1000; /* 1秒延長 */
515 break;
516 }
517}
518
519static void main_buzzer_off()
520{
521 ER ret;
522 T_EDATA *esv;
523 uint8_t p_edt[1];
524
525 switch(main_state){
526 case main_state_buzzer_on:
527 p_edt[0] = 0x42; /* 音発生無 */
528
529 /* プロパティ設定電文作成 */
530 ret = ecn_esv_seti(&esv, BUZZER_EOBJ, 0xB1, 1, p_edt);
531 if(ret != E_OK){
532 syslog(LOG_ERROR, "ecn_esv_seti");
533 break;
534 }
535
536 /* 電文送信 */
537 ecn_snd_esv(esv);
538 if(ret != E_OK){
539 syslog(LOG_ERROR, "ecn_snd_esv");
540 break;
541 }
542
543 main_state = main_state_idle;
544 main_timer = TMO_FEVR;
545 break;
546 }
547}
548
549/*
550 * 応答電文待ちの割り込み処理
551 */
552static void main_break_wait(uint8_t *brkdat, int32_t len)
553{
554 if (brkdat[0] == 0x01) {
555 // Link up/down
556 return;
557 }
558
559 if(len < 2)
560 return;
561
562 switch(brkdat[0]){
563 case 0x01:
564 if(brkdat[1] != 0)
565 main_buzzer_on();
566 else
567 main_buzzer_off();
568 break;
569 case 0x02:
570 if(brkdat[1] == 0)
571 main_nop_timer = 5000 * 1000; /* 5秒後にブザーON */
572 break;
573 }
574}
575
576static void main_ontimer();
577static void main_nop_timeout();
578
579/*
580 * タイムアウト処理
581 */
582static void main_timeout()
583{
584 if(main_timer == 0){
585 main_ontimer();
586 }
587
588 if(main_nop_timer == 0){
589 main_nop_timeout();
590 }
591}
592
593static void main_search();
594
595static void main_ontimer()
596{
597 switch (main_state)
598 {
599 case main_state_search:
600 /* 電気ポット再検索 */
601 main_search();
602 main_state = main_state_search;
603 main_timer = 5000 * 1000;
604 break;
605 case main_state_buzzer_on:
606 main_buzzer_off();
607 break;
608 default:
609 main_state = main_state_idle;
610 main_timer = TMO_FEVR;
611 break;
612 }
613}
614
615static void main_search()
616{
617 ER ret;
618 T_EDATA *esv;
619
620 /* 電気ポット検索 */
621 ret = ecn_esv_inf_req(&esv, EOBJ_NULL, 0xD6);
622 if(ret != E_OK){
623 syslog(LOG_ERROR, "ecn_esv_inf_req");
624 return;
625 }
626
627 /* 電文送信 */
628 ret = ecn_snd_esv(esv);
629 if(ret != E_OK){
630 syslog(LOG_ERROR, "ecn_snd_esv");
631 }
632}
633
634static void main_nop_timeout()
635{
636 main_buzzer_on();
637
638 main_nop_timer = TMO_FEVR;
639}
Note: See TracBrowser for help on using the repository browser.