source: asp3_tinet_ecnl_rx/trunk/app6_hot_water_pot/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: 17.1 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
54/* TODO: メーカーコードを設定 */
55#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
56
57/* ノードプロファイルオブジェクト */
58struct ecn_cls0EF0_t node_local_profile_data = {
59 0x30, /* 動作状態 */
60 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
61 {
62 0xFE, /* 下位通信層IDフィールド */
63 { MAKER_CODE }, /* メーカーコード */
64 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
65 },
66 { MAKER_CODE }, /* メーカーコード */
67};
68
69/* 電気ポットクラス */
70struct ecn_cls03B2_t electric_hot_water_pot_data = {
71 0x30, /* 動作状態 */
72 0x41, /* 湯切れ警告状態 */
73 0x41, /* 出湯状態 */
74 0x00, /* 設置場所 */
75 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
76 0x42, /* 異常発生状態 */
77 { MAKER_CODE }, /* メーカーコード */
78};
79
80/* ノードプロファイルオブジェクト */
81struct ecn_cls0EF0_t node_remote_profile_data = {
82 0x30, /* 動作状態 */
83 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
84 {
85 0xFE, /* 下位通信層IDフィールド */
86 { MAKER_CODE }, /* メーカーコード */
87 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
88 },
89 { MAKER_CODE }, /* メーカーコード */
90};
91
92/* ブザークラス */
93struct ecn_cls02A0_t buzzer_data = {
94 0x30, /* 動作状態 */
95 0x00, /* 設置場所 */
96 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
97 0x42, /* 異常発生状態 */
98 { MAKER_CODE }, /* メーカーコード */
99};
100
101/*
102 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
103 */
104int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
105{
106 /* サイズが1以外は受け付けない */
107 if(size != 1)
108 return 0;
109
110 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
111
112 switch(*(uint8_t *)src){
113 /* ONの場合 */
114 case 0x30:
115 *((uint8_t *)item->exinf) = *((uint8_t *)src);
116 /* LEDの"."をON */
117 sil_wrb_mem((uint8_t *)0x0008C028, sil_reb_mem((uint8_t *)0x0008C02A) | 0x40);
118 break;
119 /* OFFの場合 */
120 case 0x31:
121 *((uint8_t *)item->exinf) = *((uint8_t *)src);
122 /* LEDの"."をOFF */
123 sil_wrb_mem((uint8_t *)0x0008C028, sil_reb_mem((uint8_t *)0x0008C02A) & ~0x40);
124 break;
125 /* 0x30か0x31以外は受け付けない */
126 default:
127 return 0;
128 }
129
130 return 1;
131}
132
133/*
134 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
135 */
136int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
137{
138 /* サイズが1以外は受け付けない */
139 if(size != 1)
140 return 0;
141
142 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
143
144 switch(*(uint8_t *)src){
145 /* 異常発生ありの場合 */
146 case 0x41:
147 /* 異常発生なしの場合 */
148 case 0x42:
149 *((uint8_t *)item->exinf) = *((uint8_t *)src);
150 break;
151 /* 0x41か0x42以外は受け付けない */
152 default:
153 return 0;
154 }
155
156 return 1;
157}
158
159/*
160 * 湯切れ警告状態設定関数
161 */
162int no_water_warning_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
163{
164 ER ret;
165 uint8_t data[1];
166
167 /* サイズが1以外は受け付けない */
168 if(size != 1)
169 return 0;
170
171 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
172
173 switch(*(uint8_t *)src){
174 /* 湯切れ無しの場合 */
175 case 0x40:
176 *((uint8_t *)item->exinf) = *((uint8_t *)src);
177 /* LEDの"_"をOFF */
178 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) | 0x08);
179 break;
180 /* 湯切れ有りの場合 */
181 case 0x41:
182 *((uint8_t *)item->exinf) = *((uint8_t *)src);
183 /* LEDの"_"をON */
184 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) & ~0x08);
185 break;
186 /* 0x40か0x41以外は受け付けない */
187 default:
188 return 0;
189 }
190
191 /* メインタスクに通知 */
192 data[0] = 0xB1;
193 ret = ecn_brk_wai(data, sizeof(data));
194 if(ret != E_OK){
195 syslog(LOG_ERROR, "ecn_brk_wai");
196 }
197
198 return 1;
199}
200
201/*
202 * 出湯状態設定関数
203 */
204int discharge_status_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
205{
206 /* サイズが1以外は受け付けない */
207 if(size != 1)
208 return 0;
209
210 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
211
212 switch(*(uint8_t *)src){
213 /* 出湯有の場合 */
214 case 0x41:
215 *((uint8_t *)item->exinf) = *((uint8_t *)src);
216 /* LEDの上の棒をON */
217 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) & ~0x01);
218 break;
219 /* 出湯無の場合 */
220 case 0x42:
221 *((uint8_t *)item->exinf) = *((uint8_t *)src);
222 /* LEDの上の棒をOFF */
223 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) | 0x01);
224 break;
225 /* 0x41か0x42以外は受け付けない */
226 default:
227 return 0;
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 ret = ecn_brk_wai(data, sizeof(data));
339 if (ret != E_OK) {
340 syslog(LOG_ERROR, "ecn_brk_wai");
341 return;
342 }
343}
344
345enum main_state_t{
346 main_state_start,
347 main_state_idle,
348 main_state_search,
349 main_state_wait_res,
350};
351
352int main_timer = TMO_FEVR;
353enum main_state_t main_state = main_state_start;
354int main_retry;
355
356int main_btn_timer = TMO_FEVR;
357
358bool_t main_btn1_state;
359int main_btn1_count = 0;
360bool_t main_btn2_state;
361int main_btn2_count = 0;
362
363/*
364 * 初期化
365 */
366static void main_initialize()
367{
368 uint8_t btn1, btn2;
369
370 /* LEDを" "と表示 */
371 sil_wrb_mem((uint8_t *)0x0008C02A, 0x7F);
372
373 /* ECHONETミドルウェアを起動するのを待つ */
374 main_state = main_state_start;
375 main_timer = 1000 * 1000;
376
377 /* 10ms後にボタン状態を確認 */
378 main_btn_timer = 10 * 1000;
379
380 /* ボタン状態読み込み */
381 btn1 = sil_reb_mem((uint8_t *) 0x0008C04A);
382 btn2 = sil_reb_mem((uint8_t *) 0x0008C040);
383 main_btn1_state = (btn1 & 0x80) != 0;
384 main_btn2_state = (btn2 & 0x80) != 0;
385
386 /* メインタスクを起動 */
387 ER ret = act_tsk(MAIN_TASK);
388 if (ret != E_OK) {
389 syslog(LOG_ERROR, "act_tsk");
390 }
391}
392
393/*
394 * タイマー取得
395 */
396static int main_get_timer()
397{
398 int result = main_timer;
399
400 if((result == TMO_FEVR)
401 || ((main_btn_timer != TMO_FEVR) && (main_btn_timer < result))){
402 result = main_btn_timer;
403 }
404
405 return result;
406}
407
408/*
409 * 時間経過
410 */
411static void main_progress(int interval)
412{
413 if(main_timer != TMO_FEVR){
414 main_timer -= interval;
415 if(main_timer < 0){
416 main_timer = 0;
417 }
418 }
419
420 if(main_btn_timer != TMO_FEVR){
421 main_btn_timer -= interval;
422 if(main_btn_timer < 0){
423 main_btn_timer = 0;
424 }
425 }
426}
427
428/*
429 * Echonet電文受信処理
430 */
431static void main_recv_esv(T_EDATA *esv)
432{
433 ER ret;
434 ID eobjid;
435 uint8_t epc;
436 uint8_t pdc;
437 uint8_t p_edt[256];
438 T_ENUM_EPC enm;
439
440 eobjid = ecn_get_eobj(esv);
441 if(eobjid == EOBJ_NULL){
442 syslog(LOG_ERROR, "ecn_get_eobj");
443 return;
444 }
445
446 ret = ecn_itr_ini(&enm, esv);
447 if(ret != E_OK){
448 syslog(LOG_ERROR, "ecn_itr_ini");
449 return;
450 }
451
452 for(;;) {
453 while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
454 switch (epc) {
455 case 0xB1:
456 switch(main_state){
457 /* プロパティ通知応答待ちの場合 */
458 case main_state_wait_res:
459 /* プロパティ通知応答のみ処理 */
460 if((esv->hdr.edata.esv == ESV_INFC_RES) && (eobjid == BUZZER_NODE_EOBJ)){
461 /* 応答受信 */
462 main_state = main_state_idle;
463 main_timer = TMO_FEVR;
464 }
465 break;
466 }
467 break;
468 case 0xD6:
469 switch(main_state){
470 case main_state_search:
471 if (eobjid == BUZZER_NODE_EOBJ) {
472 /* ブザー検索完了 */
473 main_state = main_state_idle;
474 main_timer = TMO_FEVR;
475 }
476 break;
477 }
478 break;
479 }
480 }
481 if(ret != E_BOVR){
482 syslog(LOG_ERROR, "ecn_itr_nxt");
483 break;
484 }
485 if(enm.is_eof)
486 break;
487 }
488}
489
490/*
491 * 応答電文待ちの割り込み処理
492 */
493static void main_break_wait(uint8_t *brkdat, int32_t len)
494{
495 ER ret;
496 T_EDATA *esv;
497
498 if (brkdat[0] == 0x01) {
499 // Link up/down
500 return;
501 }
502
503 switch(main_state){
504 case main_state_idle:
505 case main_state_wait_res:
506 if((len >= 1) && (*brkdat == 0xB1)){
507 /* ブザーに湯切れ警告状態通知 */
508 ret = ecn_esv_infc(&esv, BUZZER_NODE_EOBJ, ELECTRIC_HOT_WATER_POT_EOBJ, 0xB1);
509 if(ret != E_OK){
510 syslog(LOG_ERROR, "ecn_esv_infc");
511 return;
512 }
513
514 /* 電文送信 */
515 ret = ecn_snd_esv(esv);
516 if(ret != E_OK){
517 syslog(LOG_ERROR, "ecn_snd_esv");
518 }
519
520 /* ブザーからの応答待ち(タイムアウト1秒、リトライ3回) */
521 main_state = main_state_wait_res;
522 main_timer = 1000 * 1000;
523 main_retry = 3;
524 }
525 break;
526 }
527}
528
529static void main_ontimer();
530static void main_btn_ontimer();
531
532/*
533 * タイムアウト処理
534 */
535static void main_timeout()
536{
537 if(main_timer == 0){
538 main_ontimer();
539 }
540
541 if(main_btn_timer == 0){
542 main_btn_ontimer();
543 }
544}
545
546static void main_search();
547
548static void main_ontimer()
549{
550 ER ret;
551 T_EDATA *esv;
552
553 switch(main_state){
554 case main_state_start:
555 /* ECHONETミドルウェアを起動 */
556 ret = ecn_sta_svc();
557 if (ret != E_OK) {
558 syslog(LOG_ERROR, "ecn_sta_svc");
559 }
560
561 /* 1秒後にブザーを検索 */
562 main_state = main_state_search;
563 main_timer = 1000 * 1000;
564 break;
565 case main_state_idle:
566 syslog(LOG_ERROR, "timeout faild on main_state_idle");
567 main_timer = TMO_FEVR;
568 break;
569 case main_state_search:
570 /* ブザー再検索 */
571 main_search();
572 main_state = main_state_search;
573 main_timer = 5000 * 1000;
574 break;
575 case main_state_wait_res:
576 /* リトライアウトの場合 */
577 if(main_retry == 0){
578 /* あきらめる */
579 main_state = main_state_idle;
580 main_timer = TMO_FEVR;
581 break;
582 }
583
584 /* ブザーに湯切れ警告状態通知を再送 */
585 ret = ecn_esv_infc(&esv, BUZZER_NODE_EOBJ, ELECTRIC_HOT_WATER_POT_EOBJ, 0xB1);
586 if(ret != E_OK){
587 syslog(LOG_ERROR, "ecn_esv_infc");
588 main_state = main_state_idle;
589 main_timer = TMO_FEVR;
590 return;
591 }
592
593 /* 電文送信 */
594 ret = ecn_snd_esv(esv);
595 if(ret != E_OK){
596 syslog(LOG_ERROR, "ecn_snd_esv");
597 main_state = main_state_idle;
598 main_timer = TMO_FEVR;
599 return;
600 }
601
602 /* 応答待ち */
603 main_state = main_state_wait_res;
604 main_timer = 1000 * 1000;
605 main_retry--;
606 break;
607 }
608}
609
610static void main_search()
611{
612 ER ret;
613 T_EDATA *esv;
614
615 /* ブザー検索 */
616 ret = ecn_esv_inf_req(&esv, EOBJ_NULL, 0xD6);
617 if(ret != E_OK){
618 syslog(LOG_ERROR, "ecn_esv_inf_req");
619 return;
620 }
621
622 /* 電文送信 */
623 ret = ecn_snd_esv(esv);
624 if(ret != E_OK){
625 syslog(LOG_ERROR, "ecn_snd_esv");
626 }
627}
628
629static void main_btn1_change(bool_t push);
630static void main_btn2_change(bool_t push);
631
632static void main_btn_ontimer()
633{
634 uint8_t btn1, btn2;
635
636 /* 10ms後にボタン状態を確認 */
637 main_btn_timer = 10 * 1000;
638
639 /* ボタン状態読み込み */
640 btn1 = sil_reb_mem((uint8_t *) 0x0008C04A);
641 btn2 = sil_reb_mem((uint8_t *) 0x0008C040);
642
643 /* ボタン1の処理 */
644 if(((btn1 & 0x80) != 0) && !main_btn1_state){
645 main_btn1_count++;
646 if(main_btn1_count > 10){
647 main_btn1_count = 0;
648 main_btn1_state = true;
649
650 main_btn1_change(true);
651 }
652 }
653 else if(((btn1 & 0x80) == 0) && main_btn1_state){
654 main_btn1_count++;
655 if(main_btn1_count > 10){
656 main_btn1_count = 0;
657 main_btn1_state = false;
658
659 main_btn1_change(false);
660 }
661 }
662
663 /* ボタン2の処理 */
664 if(((btn2 & 0x80) != 0) && !main_btn2_state){
665 main_btn2_count++;
666 if(main_btn2_count > 10){
667 main_btn2_count = 0;
668 main_btn2_state = true;
669
670 main_btn2_change(true);
671 }
672 }
673 else if(((btn2 & 0x80) == 0) && main_btn2_state){
674 main_btn2_count++;
675 if(main_btn2_count > 10){
676 main_btn2_count = 0;
677 main_btn2_state = false;
678
679 main_btn2_change(false);
680 }
681 }
682}
683
684bool_t main_no_wather;
685
686/*
687 * ボタン1状態変化処理
688 */
689static void main_btn1_change(bool_t push)
690{
691 ER ret;
692 T_EDATA *esv;
693 uint8_t p_edt[1];
694
695 /* 押されて戻った時に処理する */
696 if(push)
697 return;
698
699 /* 湯切れ警告状態 */
700 main_no_wather = !main_no_wather;
701
702 p_edt[0] = main_no_wather ? 0x41 : 0x40;
703
704 /* プロパティ設定電文作成 */
705 ret = ecn_esv_seti(&esv, ELECTRIC_HOT_WATER_POT_EOBJ, 0xB1, 1, p_edt);
706 if(ret != E_OK){
707 syslog(LOG_ERROR, "ecn_esv_seti");
708 return;
709 }
710
711 /* 電文送信 */
712 ecn_snd_esv(esv);
713 if(ret != E_OK){
714 syslog(LOG_ERROR, "ecn_snd_esv");
715 }
716}
717
718/*
719 * ボタン2状態変化処理
720 */
721static void main_btn2_change(bool_t push)
722{
723 ER ret;
724 T_EDATA *esv;
725 uint8_t p_edt[1];
726
727 /* 出湯操作状態(押している時が出湯あり、押していない時は出湯なし) */
728 p_edt[0] = push ? 0x41 : 0x42;
729
730 /* プロパティ設定電文作成 */
731 ret = ecn_esv_seti(&esv, ELECTRIC_HOT_WATER_POT_EOBJ, 0xE2, 1, p_edt);
732 if(ret != E_OK){
733 syslog(LOG_ERROR, "ecn_esv_seti");
734 return;
735 }
736
737 /* 電文送信 */
738 ecn_snd_esv(esv);
739 if(ret != E_OK){
740 syslog(LOG_ERROR, "ecn_snd_esv");
741 }
742}
Note: See TracBrowser for help on using the repository browser.