source: asp3_tinet_ecnl_arm/trunk/app6_hot_water_pot/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: 16.8 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 0x00, /* 設置場所 */
97 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
98 0x42, /* 異常発生状態 */
99 { MAKER_CODE }, /* メーカーコード */
100};
101
102/* 電源LED */
103gpio_t pow_led;
104/* カラーLED */
105gpio_t led_blue, led_green, led_red;
106/* ユーザースイッチ CN16-4 */
107gpio_t sw1, sw2;
108
109/*
110 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
111 */
112int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
113{
114 /* サイズが1以外は受け付けない */
115 if(size != 1)
116 return 0;
117
118 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
119
120 switch(*(uint8_t *)src){
121 /* ONの場合 */
122 case 0x30:
123 *((uint8_t *)item->exinf) = *((uint8_t *)src);
124 /* LEDをON */
125 gpio_write(&pow_led, 1);
126 break;
127 /* OFFの場合 */
128 case 0x31:
129 *((uint8_t *)item->exinf) = *((uint8_t *)src);
130 /* LEDをOFF */
131 gpio_write(&pow_led, 0);
132 break;
133 /* 0x30か0x31以外は受け付けない */
134 default:
135 return 0;
136 }
137
138 return 1;
139}
140
141/*
142 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
143 */
144int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
145{
146 /* サイズが1以外は受け付けない */
147 if(size != 1)
148 return 0;
149
150 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
151
152 switch(*(uint8_t *)src){
153 /* 異常発生ありの場合 */
154 case 0x41:
155 /* 異常発生なしの場合 */
156 case 0x42:
157 *((uint8_t *)item->exinf) = *((uint8_t *)src);
158 break;
159 /* 0x41か0x42以外は受け付けない */
160 default:
161 return 0;
162 }
163
164 return 1;
165}
166
167/*
168 * 湯切れ警告状態設定関数
169 */
170int no_water_warning_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
171{
172 ER ret;
173 uint8_t data[1];
174
175 /* サイズが1以外は受け付けない */
176 if(size != 1)
177 return 0;
178
179 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
180
181 switch(*(uint8_t *)src){
182 /* 湯切れ無しの場合 */
183 case 0x40:
184 *((uint8_t *)item->exinf) = *((uint8_t *)src);
185 /* LEDの赤をOFF */
186 gpio_write(&led_red, 0);
187 break;
188 /* 湯切れ有りの場合 */
189 case 0x41:
190 *((uint8_t *)item->exinf) = *((uint8_t *)src);
191 /* LEDの赤をON */
192 gpio_write(&led_red, 1);
193 break;
194 /* 0x40か0x41以外は受け付けない */
195 default:
196 return 0;
197 }
198
199 /* メインタスクに通知 */
200 data[0] = 0xB1;
201 ret = ecn_brk_wai(data, sizeof(data));
202 if(ret != E_OK){
203 syslog(LOG_ERROR, "ecn_brk_wai");
204 }
205
206 return 1;
207}
208
209/*
210 * 出湯状態設定関数
211 */
212int discharge_status_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
213{
214 /* サイズが1以外は受け付けない */
215 if(size != 1)
216 return 0;
217
218 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
219
220 switch(*(uint8_t *)src){
221 /* 出湯有の場合 */
222 case 0x41:
223 *((uint8_t *)item->exinf) = *((uint8_t *)src);
224 /* LEDの青をON */
225 gpio_write(&led_blue, 1);
226 break;
227 /* 出湯無の場合 */
228 case 0x42:
229 *((uint8_t *)item->exinf) = *((uint8_t *)src);
230 /* LEDの青をOFF */
231 gpio_write(&led_blue, 0);
232 break;
233 /* 0x41か0x42以外は受け付けない */
234 default:
235 return 0;
236 }
237
238 return 1;
239}
240
241static void main_initialize();
242static int main_get_timer();
243static void main_progress(int interval);
244static void main_recv_esv(T_EDATA *esv);
245static void main_break_wait(uint8_t *brkdat, int32_t len);
246static void main_timeout();
247
248/*
249 * メインタスク
250 */
251void echonet_main_task(intptr_t exinf)
252{
253 ER ret, ret2;
254 SYSTIM prev, now;
255 int timer;
256 T_EDATA *esv;
257 uint8_t brkdat[64];
258 int32_t len;
259
260 /* アプリケーションの初期化 */
261 main_initialize();
262
263 ret2 = get_tim(&now);
264 if (ret2 != E_OK){
265 syslog(LOG_ERROR, "get_tim");
266 return;
267 }
268
269 for(;;){
270 prev = now;
271
272 /* タイマー取得 */
273 timer = main_get_timer();
274
275 /* 応答電文待ち */
276 ret = ecn_trcv_esv(&esv, timer);
277 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)){
278 syslog(LOG_ERROR, "ecn_trcv_esv");
279 break;
280 }
281
282 ret2 = get_tim(&now);
283 if (ret2 != E_OK){
284 syslog(LOG_ERROR, "get_tim");
285 break;
286 }
287
288 /* 時間経過 */
289 main_progress(now - prev);
290
291 /* Echonet電文受信の場合 */
292 if (ret == E_OK) {
293 /* Echonet電文受信処理 */
294 main_recv_esv(esv);
295
296 /* 領域解放 */
297 ret = ecn_rel_esv(esv);
298 if (ret != E_OK){
299 syslog(LOG_ERROR, "ecn_rel_esv");
300 break;
301 }
302 }
303 /* 応答電文待ちの割り込みの場合 */
304 else if (ret == E_BRK) {
305 /* 応答電文待ちの割り込みデータ取得 */
306 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
307 if (ret != E_OK){
308 syslog(LOG_ERROR, "ecn_get_brk_dat");
309 break;
310 }
311
312 /* 応答電文待ちの割り込み処理 */
313 main_break_wait(brkdat, len);
314
315 /* 領域解放 */
316 ret = ecn_rel_esv(esv);
317 if (ret != E_OK){
318 syslog(LOG_ERROR, "ecn_rel_esv");
319 break;
320 }
321 }
322
323 /* タイムアウト処理 */
324 main_timeout();
325 }
326}
327
328bool_t started = false;
329
330void echonet_change_netif_link(uint8_t link_up, uint8_t up)
331{
332 ER ret;
333
334 if (link_up == 0)
335 return;
336
337 if (up && !started) {
338 started = true;
339
340 /* ECHONETミドルウェアを起動 */
341 ret = ecn_sta_svc();
342 if (ret != E_OK)
343 return;
344
345 /* ECHONETミドルウェアを起動するのを待つ */
346 dly_tsk(100);
347 }
348
349 /* メインタスクに通知 */
350 uint8_t data[2];
351 data[0] = 0x01;
352 data[1] = up ? 0x01 : 0x02;
353 ret = ecn_brk_wai(data, sizeof(data));
354 if (ret != E_OK) {
355 syslog(LOG_ERROR, "ecn_brk_wai");
356 return;
357 }
358}
359
360enum main_state_t{
361 main_state_idle,
362 main_state_search,
363 main_state_wait_res,
364};
365
366int main_timer = TMO_FEVR;
367enum main_state_t main_state = main_state_idle;
368int main_retry;
369
370int main_btn_timer = TMO_FEVR;
371
372bool_t main_btn1_state;
373int main_btn1_count = 0;
374bool_t main_btn2_state;
375int main_btn2_count = 0;
376
377/*
378 * 初期化
379 */
380static void main_initialize()
381{
382 uint8_t btn1, btn2;
383
384 /* LEDの初期化 */
385 gpio_init_out(&pow_led, LED_USER);
386 gpio_init_out(&led_blue, LED_BLUE);
387 gpio_init_out(&led_green, LED_GREEN);
388 gpio_init_out(&led_red, LED_RED);
389
390 /* スイッチの初期化 */
391 gpio_init_in(&sw1, USER_BUTTON0);
392 gpio_init_in(&sw2, P1_12);
393
394 /* カラーLEDを消灯 */
395 gpio_write(&led_blue, 0);
396 gpio_write(&led_green, 0);
397 gpio_write(&led_red, 0);
398
399 /* 1秒後にブザーを検索 */
400 main_state = main_state_search;
401 main_timer = 1000 * 1000;
402
403 /* 10ms後にボタン状態を確認 */
404 main_btn_timer = 10 * 1000;
405
406 /* ボタン状態読み込み */
407 btn1 = gpio_read(&sw1);
408 btn2 = gpio_read(&sw2);
409 main_btn1_state = btn1 != 0;
410 main_btn2_state = btn2 != 0;
411
412 ER ret = act_tsk(MAIN_TASK);
413 if (ret != E_OK) {
414 syslog(LOG_ERROR, "act_tsk");
415 }
416}
417
418/*
419 * タイマー取得
420 */
421static int main_get_timer()
422{
423 int result = main_timer;
424
425 if((result == TMO_FEVR)
426 || ((main_btn_timer != TMO_FEVR) && (main_btn_timer < result))){
427 result = main_btn_timer;
428 }
429
430 return result;
431}
432
433/*
434 * 時間経過
435 */
436static void main_progress(int interval)
437{
438 if(main_timer != TMO_FEVR){
439 main_timer -= interval;
440 if(main_timer < 0){
441 main_timer = 0;
442 }
443 }
444
445 if(main_btn_timer != TMO_FEVR){
446 main_btn_timer -= interval;
447 if(main_btn_timer < 0){
448 main_btn_timer = 0;
449 }
450 }
451}
452
453/*
454 * Echonet電文受信処理
455 */
456static void main_recv_esv(T_EDATA *esv)
457{
458 ER ret;
459 ID eobjid;
460 uint8_t epc;
461 uint8_t pdc;
462 uint8_t p_edt[256];
463 T_ENUM_EPC enm;
464
465 eobjid = ecn_get_eobj(esv);
466 if(eobjid == EOBJ_NULL){
467 syslog(LOG_ERROR, "ecn_get_eobj");
468 return;
469 }
470
471 ret = ecn_itr_ini(&enm, esv);
472 if(ret != E_OK){
473 syslog(LOG_ERROR, "ecn_itr_ini");
474 return;
475 }
476
477 for(;;) {
478 while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
479 switch (epc) {
480 case 0xB1:
481 switch(main_state){
482 /* プロパティ通知応答待ちの場合 */
483 case main_state_wait_res:
484 /* プロパティ通知応答のみ処理 */
485 if((esv->hdr.edata.esv == ESV_INFC_RES) && (eobjid == BUZZER_NODE_EOBJ)){
486 /* 応答受信 */
487 main_state = main_state_idle;
488 main_timer = TMO_FEVR;
489 }
490 break;
491 }
492 break;
493 case 0xD6:
494 switch(main_state){
495 case main_state_search:
496 if (eobjid == BUZZER_NODE_EOBJ) {
497 /* ブザー検索完了 */
498 main_state = main_state_idle;
499 main_timer = TMO_FEVR;
500 }
501 break;
502 }
503 break;
504 }
505 }
506 if(ret != E_BOVR){
507 syslog(LOG_ERROR, "ecn_itr_nxt");
508 break;
509 }
510 if(enm.is_eof)
511 break;
512 }
513}
514
515/*
516 * 応答電文待ちの割り込み処理
517 */
518static void main_break_wait(uint8_t *brkdat, int32_t len)
519{
520 ER ret;
521 T_EDATA *esv;
522
523 if (brkdat[0] == 0x01) {
524 // Link up/down
525 return;
526 }
527
528 switch(main_state){
529 case main_state_idle:
530 case main_state_wait_res:
531 if((len >= 1) && (*brkdat == 0xB1)){
532 /* ブザーに湯切れ警告状態通知 */
533 ret = ecn_esv_infc(&esv, BUZZER_NODE_EOBJ, ELECTRIC_HOT_WATER_POT_EOBJ, 0xB1);
534 if(ret != E_OK){
535 syslog(LOG_ERROR, "ecn_esv_infc");
536 return;
537 }
538
539 /* 電文送信 */
540 ret = ecn_snd_esv(esv);
541 if(ret != E_OK){
542 syslog(LOG_ERROR, "ecn_snd_esv");
543 }
544
545 /* ブザーからの応答待ち(タイムアウト1秒、リトライ3回) */
546 main_state = main_state_wait_res;
547 main_timer = 1000 * 1000;
548 main_retry = 3;
549 }
550 break;
551 }
552}
553
554static void main_ontimer();
555static void main_btn_ontimer();
556
557/*
558 * タイムアウト処理
559 */
560static void main_timeout()
561{
562 if(main_timer == 0){
563 main_ontimer();
564 }
565
566 if(main_btn_timer == 0){
567 main_btn_ontimer();
568 }
569}
570
571static void main_search();
572
573static void main_ontimer()
574{
575 ER ret;
576 T_EDATA *esv;
577
578 switch(main_state){
579 case main_state_idle:
580 syslog(LOG_ERROR, "timeout faild on main_state_idle");
581 main_timer = TMO_FEVR;
582 break;
583 case main_state_search:
584 /* ブザー再検索 */
585 main_search();
586 main_state = main_state_search;
587 main_timer = 5000 * 1000;
588 break;
589 case main_state_wait_res:
590 /* リトライアウトの場合 */
591 if(main_retry == 0){
592 /* あきらめる */
593 main_state = main_state_idle;
594 main_timer = TMO_FEVR;
595 break;
596 }
597
598 /* ブザーに湯切れ警告状態通知を再送 */
599 ret = ecn_esv_infc(&esv, BUZZER_NODE_EOBJ, ELECTRIC_HOT_WATER_POT_EOBJ, 0xB1);
600 if(ret != E_OK){
601 syslog(LOG_ERROR, "ecn_esv_infc");
602 main_state = main_state_idle;
603 main_timer = TMO_FEVR;
604 return;
605 }
606
607 /* 電文送信 */
608 ret = ecn_snd_esv(esv);
609 if(ret != E_OK){
610 syslog(LOG_ERROR, "ecn_snd_esv");
611 main_state = main_state_idle;
612 main_timer = TMO_FEVR;
613 return;
614 }
615
616 /* 応答待ち */
617 main_state = main_state_wait_res;
618 main_timer = 1000 * 1000;
619 main_retry--;
620 break;
621 }
622}
623
624static void main_search()
625{
626 ER ret;
627 T_EDATA *esv;
628
629 /* ブザー検索 */
630 ret = ecn_esv_inf_req(&esv, EOBJ_NULL, 0xD6);
631 if(ret != E_OK){
632 syslog(LOG_ERROR, "ecn_esv_inf_req");
633 return;
634 }
635
636 /* 電文送信 */
637 ret = ecn_snd_esv(esv);
638 if(ret != E_OK){
639 syslog(LOG_ERROR, "ecn_snd_esv");
640 }
641}
642
643static void main_btn1_change(bool_t push);
644static void main_btn2_change(bool_t push);
645
646static void main_btn_ontimer()
647{
648 uint8_t btn1, btn2;
649
650 /* 10ms後にボタン状態を確認 */
651 main_btn_timer = 10 * 1000;
652
653 /* ボタン状態読み込み */
654 btn1 = gpio_read(&sw1);
655 btn2 = gpio_read(&sw2);
656
657 /* ボタン1の処理 */
658 if((btn1 != 0) && !main_btn1_state){
659 main_btn1_count++;
660 if(main_btn1_count > 10){
661 main_btn1_count = 0;
662 main_btn1_state = true;
663
664 main_btn1_change(true);
665 }
666 }
667 else if((btn1 == 0) && main_btn1_state){
668 main_btn1_count++;
669 if(main_btn1_count > 10){
670 main_btn1_count = 0;
671 main_btn1_state = false;
672
673 main_btn1_change(false);
674 }
675 }
676
677 /* ボタン2の処理 */
678 if((btn2 != 0) && !main_btn2_state){
679 main_btn2_count++;
680 if(main_btn2_count > 10){
681 main_btn2_count = 0;
682 main_btn2_state = true;
683
684 main_btn2_change(true);
685 }
686 }
687 else if((btn2 == 0) && main_btn2_state){
688 main_btn2_count++;
689 if(main_btn2_count > 10){
690 main_btn2_count = 0;
691 main_btn2_state = false;
692
693 main_btn2_change(false);
694 }
695 }
696}
697
698bool_t main_no_wather;
699
700/*
701 * ボタン1状態変化処理
702 */
703static void main_btn1_change(bool_t push)
704{
705 ER ret;
706 T_EDATA *esv;
707 uint8_t p_edt[1];
708
709 /* 押されて戻った時に処理する */
710 if(push)
711 return;
712
713 /* 湯切れ警告状態 */
714 main_no_wather = !main_no_wather;
715
716 p_edt[0] = main_no_wather ? 0x41 : 0x40;
717
718 /* プロパティ設定電文作成 */
719 ret = ecn_esv_seti(&esv, ELECTRIC_HOT_WATER_POT_EOBJ, 0xB1, 1, p_edt);
720 if(ret != E_OK){
721 syslog(LOG_ERROR, "ecn_esv_seti");
722 return;
723 }
724
725 /* 電文送信 */
726 ecn_snd_esv(esv);
727 if(ret != E_OK){
728 syslog(LOG_ERROR, "ecn_snd_esv");
729 }
730}
731
732/*
733 * ボタン2状態変化処理
734 */
735static void main_btn2_change(bool_t push)
736{
737 ER ret;
738 T_EDATA *esv;
739 uint8_t p_edt[1];
740
741 /* 出湯操作状態(押している時が出湯あり、押していない時は出湯なし) */
742 p_edt[0] = push ? 0x41 : 0x42;
743
744 /* プロパティ設定電文作成 */
745 ret = ecn_esv_seti(&esv, ELECTRIC_HOT_WATER_POT_EOBJ, 0xE2, 1, p_edt);
746 if(ret != E_OK){
747 syslog(LOG_ERROR, "ecn_esv_seti");
748 return;
749 }
750
751 /* 電文送信 */
752 ecn_snd_esv(esv);
753 if(ret != E_OK){
754 syslog(LOG_ERROR, "ecn_snd_esv");
755 }
756}
Note: See TracBrowser for help on using the repository browser.