source: EcnlProtoTool/trunk/mrbgems/mruby-ecnl/src/echonet_agent.c@ 321

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

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 31.1 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2015-2016 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 * ECHONET Lite 動的生成ノード
40 */
41
42#include <mruby.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <stdarg.h>
46#include <string.h>
47#ifdef _MSC_VER
48#include <assert.h>
49#endif
50#include "echonet_task.h"
51#include "echonet_dbg.h"
52
53static ER ecn_agent_proc_get_device_list(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req);
54static ER ecn_agent_proc_get_device_info(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req);
55static void ecn_node_send_set_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
56static void ecn_node_send_get_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
57static void ecn_node_send_anno_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
58static void ecn_node_timeout_on_start(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
59static void ecn_node_next_proc_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj);
60static void ecn_node_timeout_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
61static void ecn_node_next_proc_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj);
62static void ecn_node_timeout_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
63static void ecn_node_next_proc_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj);
64static void ecn_node_timeout_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
65
66int ecn_agent_eprpset(ecnl_svc_task_t *svc, const EPRPINIB *item, const void *src, int size, bool_t *anno);
67int ecn_agent_eprpget(ecnl_svc_task_t *svc, const EPRPINIB *item, void *dst, int size);
68
69static ecn_agent_queue_t *cast_queue(ecn_obj_t *obj)
70{
71 return (ecn_agent_queue_t *)((intptr_t)obj - offsetof(ecn_agent_buffer_t, cnt.obj));
72}
73
74static ecn_obj_t *cast_obj(ecn_agent_queue_t *queue)
75{
76 return (ecn_obj_t *)((intptr_t)queue + offsetof(ecn_agent_buffer_t, cnt.obj));
77}
78
79static ecn_node_agent_t *cast_node(const EOBJCB *eobj)
80{
81 return (ecn_node_agent_t *)((intptr_t)eobj - offsetof(ecn_node_agent_t, node.eobj));
82}
83
84static ecn_obj_t *cast_obj2(const EOBJINIB *inib)
85{
86 return (ecn_obj_t *)((intptr_t)inib - offsetof(ecn_obj_t, inib));
87}
88
89static ecn_agent_t *cast_agent(const EPRPINIB *inib)
90{
91 return (ecn_agent_t *)((intptr_t)inib - offsetof(ecn_agent_t, eprpinib));
92}
93
94#define loc_cpu()
95#define unl_cpu()
96
97ER get_buf(ecn_agent_t *agent, ecn_agent_buffer_t **buf)
98{
99 ER ret = E_OK;
100
101 loc_cpu();
102
103 if (agent->blkpos < TNUM_AEOBJID) {
104 *buf = &agent->blockes[agent->blkpos++];
105 }
106 else if (agent->free == NULL) {
107 ret = E_TMOUT;
108 }
109 else{
110 *buf = agent->free;
111 agent->free = agent->free->hdr.free;
112 }
113
114 unl_cpu();
115
116 return ret;
117}
118
119ER rel_buf(ecn_agent_t *agent, ecn_agent_buffer_t *buf)
120{
121 if ((buf < &agent->blockes[0]) || (buf >= &agent->blockes[TNUM_AEOBJID]))
122 return E_PAR;
123
124 if ((((intptr_t)buf - (intptr_t)&agent->blockes[0]) % sizeof(ecn_agent_buffer_t)) != 0)
125 return E_PAR;
126
127 loc_cpu();
128
129 if (agent->free == NULL) {
130 agent->free = buf;
131 agent->free->hdr.free = NULL;
132 }
133 else {
134 ecn_agent_buffer_t *next = agent->free;
135 agent->free = buf;
136 agent->free->hdr.free = next;
137 }
138
139 unl_cpu();
140
141 return E_OK;
142}
143
144/*
145 * キューの初期化
146 *
147 * p_queueにはキューヘッダを指定する.
148 */
149static void
150ecn_agent_queue_init(ecn_agent_queue_t *p_queue)
151{
152#ifdef _DEBUG
153 p_queue->p_parent = p_queue;
154#endif
155 p_queue->p_prev = p_queue;
156 p_queue->p_next = p_queue;
157}
158
159/*
160 * キューの前エントリへの挿入
161 *
162 * p_queueの前にp_entryを挿入する.p_queueにキューヘッダを指定した場
163 * 合には,キューの末尾にp_entryを挿入することになる.
164 */
165static void
166ecn_agent_queue_add(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
167{
168#ifdef _DEBUG
169 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == NULL));
170 p_entry->p_parent = p_queue;
171#endif
172 p_entry->p_prev = p_queue->p_prev;
173 p_entry->p_next = p_queue;
174 p_queue->p_prev->p_next = p_entry;
175 p_queue->p_prev = p_entry;
176}
177
178/*
179 * エントリの削除
180 *
181 * p_entryをキューから削除する.
182 */
183static void
184ecn_agent_queue_remove(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
185{
186#ifdef _DEBUG
187 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == p_queue));
188 p_entry->p_parent = NULL;
189#endif
190 p_entry->p_prev->p_next = p_entry->p_next;
191 p_entry->p_next->p_prev = p_entry->p_prev;
192}
193
194ecn_node_t *ecn_agent_find_node(ecnl_svc_task_t *svc, ECN_ENOD_ID enodid)
195{
196 ecn_agent_t *agent = &svc->agent;
197 ecn_agent_queue_t *queue = agent->nodes.p_next;
198#ifdef _DEBUG
199 assert(queue->p_parent == &agent->nodes);
200#endif
201 for (; queue != &agent->nodes; queue = queue->p_next) {
202 ecn_node_t *node = (ecn_node_t *)cast_obj(queue);
203 if(node->enodId == enodid)
204 return node;
205 }
206
207 return NULL;
208}
209
210ecn_node_agent_t *ecn_agent_find_node2(ecnl_svc_task_t *svc, const EOBJCB *pk_eobj)
211{
212 ecn_agent_t *agent = &svc->agent;
213 ecn_agent_queue_t *queue;
214
215 if(pk_eobj == NULL)
216 return NULL;
217
218 queue = agent->nodes.p_next;
219#ifdef _DEBUG
220 assert(queue->p_parent == &agent->nodes);
221#endif
222 for (; queue != &agent->nodes; queue = queue->p_next) {
223 ecn_node_agent_t *node = (ecn_node_agent_t *)cast_obj(queue);
224 if(&node->node.eobj == pk_eobj)
225 return node;
226 }
227
228 return NULL;
229}
230
231ecn_obj_t *ecn_agent_find_eobj(const EOBJCB *pk_nod, T_ECN_EOJ eoj)
232{
233 ecn_agent_queue_t *devices = &cast_node(pk_nod)->node.devices;
234 ecn_agent_queue_t *queue = devices->p_next;
235#ifdef _DEBUG
236 assert(queue->p_parent == devices);
237#endif
238 for (; queue != devices; queue = queue->p_next) {
239 ecn_obj_t *obj = cast_obj(queue);
240 if (obj->inib.eojx1 != eoj.eojx1)
241 continue;
242 if (obj->inib.eojx2 != eoj.eojx2)
243 continue;
244 if (obj->inib.eojx3 != eoj.eojx3)
245 continue;
246
247 return obj;
248 }
249
250 return NULL;
251}
252
253ecn_obj_t *ecn_agent_find_obj2(ecn_node_agent_t *pk_nod, const EOBJINIB *pk_obj)
254{
255 ecn_agent_queue_t *devices = &pk_nod->node.devices;
256 ecn_agent_queue_t *queue = devices->p_next;
257#ifdef _DEBUG
258 assert(queue->p_parent == devices);
259#endif
260 for (; queue != devices; queue = queue->p_next) {
261 ecn_obj_t *obj = cast_obj(queue);
262 if (&obj->inib == pk_obj)
263 return obj;
264 }
265
266 return NULL;
267}
268
269ID ecn_agent_get_eobj(const EOBJINIB *pk_obj)
270{
271 return cast_obj2(pk_obj)->eobjId;
272}
273
274const EOBJINIB *ecn_agent_next_eobj(const EOBJCB *pk_nod, const EOBJINIB *pk_obj)
275{
276 ecn_agent_queue_t *devices = &cast_node(pk_nod)->node.devices;
277 ecn_obj_t *device = (ecn_obj_t *)pk_obj->exinf;
278 ecn_agent_queue_t *queue = cast_queue(device);
279#ifdef _DEBUG
280 assert(queue->p_parent == devices);
281#endif
282 if (queue == devices)
283 return NULL;
284
285 return &cast_obj(queue->p_next)->inib;
286}
287
288bool_t ecn_agent_get_eoj_enodid(ecnl_svc_task_t *svc, ID eobjid, T_ECN_EOJ *eoj, ECN_ENOD_ID *enodid)
289{
290 ecn_agent_t *agent = &svc->agent;
291 ecn_agent_buffer_t *buf;
292 int i = eobjid;
293
294 /* オブジェクトIDから実体を取得 */
295 i -= (svc->tmax_eobjid + 1);
296 if ((i < 0)
297 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
298 return false;
299 }
300
301 buf = &agent->blockes[i];
302 if(buf->cnt.obj.eobjId != eobjid)
303 return false;
304
305 /* オブジェクトのEOJをコピー */
306 memcpy(eoj, &buf->cnt.obj.inib.eojx1, sizeof(*eoj));
307
308 /* 所属するノードのオブジェクトIDを取得 */
309 if(buf->cnt.obj.inib.enodid == 0)
310 i = buf->cnt.obj.eobjId;
311 else
312 i = buf->cnt.obj.inib.enodid;
313
314 i -= (svc->tmax_eobjid + 1);
315 if ((i < 0)
316 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
317 return false;
318 }
319
320 /* ノードIDを取得 */
321 buf = &agent->blockes[i];
322 *enodid = buf->cnt.node.node.enodId;
323
324 return true;
325}
326
327void ecn_agent_set_epc_to_prop_map(uint8_t epc, uint8_t *propMap)
328{
329 int i, j;
330 if ((epc & 0x80) == 0)
331 return;
332 i = epc & 0xF;
333 j = (epc >> 4) - 8;
334 propMap[i] |= (1 << j);
335}
336
337bool_t ecn_agent_contains_epc_in_prop_map(uint8_t epc, uint8_t *propMap)
338{
339 int i, j;
340 if ((epc & 0x80) == 0)
341 return false;
342 i = epc & 0xF;
343 j = (epc >> 4) - 8;
344 return (propMap[i] & (1 << j)) != 0;
345}
346
347void ecn_agent_init(ecnl_svc_task_t *svc)
348{
349 svc->agent.eprpinib.eprpcd = 0x00; /* プロパティコード */
350 svc->agent.eprpinib.eprpatr = EPC_RULE_SET | EPC_RULE_GET; /* プロパティ属性 */
351 svc->agent.eprpinib.eprpsz = 255; /* プロパティのサイズ */
352 svc->agent.eprpinib.exinf = (intptr_t)&svc->agent; /* プロパティの拡張情報 */
353 svc->agent.eprpinib.eprpset = ecn_agent_eprpset; /* プロパティの設定関数 */
354 svc->agent.eprpinib.eprpget = ecn_agent_eprpget; /* プロパティの取得関数 */
355
356 svc->agent.peprpinib = &svc->agent.eprpinib;
357
358 ecn_agent_queue_init(&svc->agent.nodes);
359}
360
361ecn_node_agent_t *ecn_agent_create_node(ecnl_svc_task_t *svc, ecn_agent_t *agent, T_EDATA *esv)
362{
363 mrb_state *mrb = svc->mrb;
364 ecn_agent_buffer_t *result = NULL;
365 ecn_node_agent_t *node;
366 uint8_t epc;
367 uint8_t pdc;
368 uint8_t edt[256];
369 T_ENUM_EPC enm;
370 ER ret;
371 T_ECN_EOJ *eoj, *end;
372
373 // プロパティ通知か取得応答で、
374 switch (esv->hdr.edata.esv) {
375 case ESV_GET_RES:
376 case ESV_GET_SNA:
377 case ESV_INF:
378 break;
379 default:
380 return NULL;
381 }
382
383 // ノードプロファイル宛の場合
384 eoj = &esv->hdr.edata.seoj;
385 if ((eoj->eojx1 != EOJ_X1_PROFILE) || (eoj->eojx2 != EOJ_X2_NODE_PROFILE)
386 || (eoj->eojx3 != 0x01))
387 return NULL;
388
389 ret = ecn_itr_ini(&enm, esv);
390 if(ret != E_OK){
391 ECN_DBG_PUT("ecn_itr_ini");
392 }
393
394 while (ecn_itr_nxt(mrb, &enm, &epc, &pdc, &edt) == E_OK) {
395 switch (epc) {
396 // インスタンスリスト通知の場合
397 case 0xD5:
398 // 自ノードインスタンスリストS通知の場合
399 case 0xD6:
400 // サイズが合わない場合
401 if (pdc != (1 + edt[0] * sizeof(T_ECN_EOJ)))
402 return NULL;
403
404 ret = get_buf(agent, &result);
405 if(ret != E_OK){
406 ECN_DBG_PUT("get_buf");
407 return NULL;
408 }
409
410 memset(result, 0, sizeof(*result));
411 node = &result->cnt.node;
412 node->node.enodId = ((T_ECN_FST_BLK *)esv)->hdr.sender.id;
413 node->node.base.svc = svc;
414 node->node.base.eobjId = svc->tmax_eobjid + 1 + (((intptr_t)result - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
415 node->node.base.inib.enodid = 0;
416 node->node.base.inib.eobjatr = EOBJ_SYNC_REMOTE_NODE;
417 node->node.base.inib.exinf = (intptr_t)node;
418 node->node.base.inib.eojx1 = eoj->eojx1;
419 node->node.base.inib.eojx2 = eoj->eojx2;
420 node->node.base.inib.eojx3 = eoj->eojx3;
421 node->node.base.inib.eprp = &agent->peprpinib;
422 node->node.base.inib.eprpcnt = 0;
423 ecn_agent_set_epc_to_prop_map(0xD5, node->node.base.pmapGet);
424 ecn_agent_set_epc_to_prop_map(0xD6, node->node.base.pmapGet);
425 ecn_agent_set_epc_to_prop_map(0x9D, node->node.base.pmapGet);
426 ecn_agent_set_epc_to_prop_map(0x9E, node->node.base.pmapGet);
427 ecn_agent_set_epc_to_prop_map(0x9F, node->node.base.pmapGet);
428 ecn_agent_queue_init(&node->node.devices);
429 node->node.eobj.profile = &node->node.base.inib;
430 node->node.eobj.eobjs = NULL;
431 node->node.eobj.eobjcnt = pdc / 3;
432 node->state = ecn_node_state_idle;
433 node->timer = TMO_FEVR;
434
435 end = (T_ECN_EOJ *)&edt[pdc];
436 for (eoj = (T_ECN_EOJ *)&edt[1]; eoj < end; eoj++) {
437 ecn_device_t *device;
438 ecn_agent_buffer_t *obj;
439
440 ret = get_buf(agent, &obj);
441 if(ret != E_OK){
442 ECN_DBG_PUT("get_buf");
443 return NULL;
444 }
445
446 memset(obj, 0, sizeof(*obj));
447 device = &obj->cnt.device;
448 device->node = &node->node;
449 device->base.svc = svc;
450 device->base.eobjId = svc->tmax_eobjid + 1 + (((intptr_t)obj - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
451 device->base.inib.eobjatr = EOBJ_DEVICE;
452 device->base.inib.enodid = node->node.base.eobjId;
453 device->base.inib.exinf = (intptr_t)device;
454 device->base.inib.eojx1 = eoj->eojx1;
455 device->base.inib.eojx2 = eoj->eojx2;
456 device->base.inib.eojx3 = eoj->eojx3;
457 device->base.inib.eprp = &agent->peprpinib;
458 device->base.inib.eprpcnt = 0;
459 ecn_agent_set_epc_to_prop_map(0x9D, device->base.pmapGet);
460 ecn_agent_set_epc_to_prop_map(0x9E, device->base.pmapGet);
461 ecn_agent_set_epc_to_prop_map(0x9F, device->base.pmapGet);
462
463 ecn_agent_queue_add(&node->node.devices, &obj->hdr.queue);
464 }
465 break;
466 default:
467 continue;
468 }
469 break;
470 }
471
472 if (result == NULL)
473 return NULL;
474
475 ecn_agent_queue_add(&agent->nodes, &result->hdr.queue);
476
477 return node;
478}
479
480static ER ecn_agent_proc_get_device_list(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req)
481{
482 mrb_state *mrb = svc->mrb;
483 ER ret;
484 ECN_FBS_ID res;
485 ecn_inm_get_device_list_req_t msg;
486 ECN_FBS_SSIZE_T len;
487 ecn_agent_buffer_t *pos, *end = &agent->blockes[TNUM_AEOBJID];
488 ecn_inm_get_device_item_t item;
489 int i, j;
490
491 ret = _ecn_fbs_get_data(mrb, req, &msg, sizeof(msg), &len);
492 if (ret != E_OK) {
493 return ret;
494 }
495
496 ret = _ecn_tsk_cre_res_fbs(svc, req, ECN_INM_GET_DEVICE_LIST_RES, &res);
497 if (ret != E_OK) {
498 return ret;
499 }
500
501 ret = _ecn_fbs_add_data_ex(mrb, res, &msg.requestid, sizeof(((ecn_inm_get_device_list_res_t *)0)->requestid));
502 if (ret != E_OK) {
503 _ecn_fbs_del(mrb, res);
504 return ret;
505 }
506
507 for (i = 0; i < svc->tnum_enodid; i++) {
508 const EOBJCB *enod = &svc->eobjcb_table[i];
509 for (j = 0; j < enod->eobjcnt; j++) {
510 const EOBJINIB *eobj = enod->eobjs[i];
511 item.eobjid = echonet_svctask_get_eobjid(svc, eobj);
512 item.enodid = eobj->enodid;
513 item.state = true;
514 item.eojx1 = eobj->eojx1;
515 item.eojx2 = eobj->eojx2;
516 item.eojx3 = eobj->eojx3;
517 item.addrid = (i == 0) ? ENOD_LOCAL_ID : (ENOD_REMOTE_ID + i);
518
519 ret = _ecn_fbs_add_data_ex(mrb, res, &item, sizeof(item));
520 if (ret != E_OK) {
521 _ecn_fbs_del(mrb, res);
522 return ret;
523 }
524 }
525 }
526
527 for (pos = &agent->blockes[0]; pos < end; pos++){
528 if(pos->cnt.obj.eobjId == 0)
529 continue;
530
531 item.eobjid = pos->cnt.obj.eobjId;
532 item.enodid = pos->cnt.obj.inib.enodid;
533 item.state = (pos->cnt.obj.pmapFlag & (PMAP_FLAG_SET | PMAP_FLAG_GET | PMAP_FLAG_ANNO))
534 == (PMAP_FLAG_SET | PMAP_FLAG_GET | PMAP_FLAG_ANNO);
535 item.eojx1 = pos->cnt.obj.inib.eojx1;
536 item.eojx2 = pos->cnt.obj.inib.eojx2;
537 item.eojx3 = pos->cnt.obj.inib.eojx3;
538
539 if(pos->cnt.device.node != NULL)
540 item.addrid = pos->cnt.device.node->enodId;
541 else
542 item.addrid = pos->cnt.node.node.enodId;
543
544 ret = _ecn_fbs_add_data_ex(mrb, res, &item, sizeof(item));
545 if (ret != E_OK) {
546 _ecn_fbs_del(mrb, res);
547 return ret;
548 }
549 }
550
551 ret = ecn_fbs_enqueue(res.ptr->hdr.target.mbxid, res.ptr);
552 if (ret != E_OK) {
553 _ecn_fbs_del(mrb, res);
554 return ret;
555 }
556
557 return E_OK;
558}
559
560static ER ecn_agent_proc_get_device_info(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req)
561{
562 mrb_state *mrb = svc->mrb;
563 ER ret;
564 ECN_FBS_ID res;
565 ecn_inm_get_device_info_req_t msg;
566 ecn_inm_get_device_info_res_t rmsg;
567 ECN_FBS_SSIZE_T len;
568
569 ret = _ecn_fbs_get_data(mrb, req, &msg, sizeof(msg), &len);
570 if (ret != E_OK) {
571 return ret;
572 }
573
574 memset(&rmsg, 0, sizeof(rmsg));
575
576 if (msg.eobjid <= svc->tmax_eobjid) {
577 const EOBJINIB *eobj = echonet_svctask_get_eobjinib(svc, msg.eobjid);
578 int i;
579
580 rmsg.requestid = msg.requestid;
581 rmsg.eobjid = msg.eobjid;
582 for (i = 0; i < eobj->eprpcnt; i++) {
583 uint8_t epc = eobj->eprp[i]->eprpcd;
584 ecn_agent_set_epc_to_prop_map(epc, rmsg.pmapSet);
585 ecn_agent_set_epc_to_prop_map(epc, rmsg.pmapGet);
586 ecn_agent_set_epc_to_prop_map(epc, rmsg.pmapAnno);
587 }
588 rmsg.eprpcnt = eobj->eprpcnt;
589 }
590 else {
591 int eobjId;
592 ecn_agent_buffer_t *pos;
593
594 eobjId = msg.eobjid - svc->tmax_eobjid - 1;
595 pos = &agent->blockes[eobjId];
596
597 rmsg.requestid = msg.requestid;
598 rmsg.eobjid = pos->cnt.obj.eobjId;
599 memcpy(rmsg.pmapSet, pos->cnt.obj.pmapSet, sizeof(rmsg.pmapSet));
600 memcpy(rmsg.pmapGet, pos->cnt.obj.pmapGet, sizeof(rmsg.pmapGet));
601 memcpy(rmsg.pmapAnno, pos->cnt.obj.pmapAnno, sizeof(rmsg.pmapAnno));
602 rmsg.eprpcnt = pos->cnt.obj.eprpcnt;
603 }
604
605 ret = _ecn_tsk_cre_res_fbs(svc, req, ECN_INM_GET_DEVICE_INFO_RES, &res);
606 if (ret != E_OK) {
607 return ret;
608 }
609
610 ret = _ecn_fbs_add_data_ex(mrb, res, &rmsg, sizeof(rmsg));
611 if (ret != E_OK) {
612 _ecn_fbs_del(mrb, res);
613 return ret;
614 }
615
616 ret = ecn_fbs_enqueue(res.ptr->hdr.target.mbxid, res.ptr);
617 if (ret != E_OK) {
618 _ecn_fbs_del(mrb, res);
619 return ret;
620 }
621
622 return E_OK;
623}
624
625TMO ecn_agent_get_timer(ecnl_svc_task_t *svc)
626{
627 TMO timer = TMO_FEVR, temp;
628 ecn_agent_t *agent = &svc->agent;
629 ecn_node_agent_t *node;
630 ecn_agent_queue_t *queue;
631
632 queue = &agent->nodes;
633 for (;;) {
634 queue = queue->p_next;
635#ifdef _DEBUG
636 assert(queue->p_parent == &agent->nodes);
637#endif
638 if(&agent->nodes == queue)
639 break;
640
641 node = (ecn_node_agent_t *)cast_obj(queue);
642 temp = node->timer;
643 if (temp != TMO_FEVR) {
644 if ((timer == TMO_FEVR) || (temp < timer)) {
645 timer = temp;
646 }
647 }
648 }
649
650 return timer;
651}
652
653void ecn_agent_progress(ecnl_svc_task_t *svc, TMO interval)
654{
655 ecn_agent_t *agent = &svc->agent;
656 ecn_node_agent_t *node;
657 ecn_agent_queue_t *queue;
658
659 queue = &agent->nodes;
660 for (;;) {
661 queue = queue->p_next;
662#ifdef _DEBUG
663 assert(queue->p_parent == &agent->nodes);
664#endif
665 if(&agent->nodes == queue)
666 break;
667
668 node = (ecn_node_agent_t *)cast_obj(queue);
669 if (node->timer == TMO_FEVR)
670 continue;
671
672 node->timer -= interval;
673 if (node->timer <= 0) {
674 node->timer = 0;
675 }
676 }
677}
678
679void ecn_agent_timeout(ecnl_svc_task_t *svc)
680{
681 ecn_agent_t *agent = &svc->agent;
682 ecn_node_agent_t *node;
683 ecn_agent_queue_t *queue;
684
685 queue = &agent->nodes;
686 for (;;) {
687 queue = queue->p_next;
688#ifdef _DEBUG
689 assert(queue->p_parent == &agent->nodes);
690#endif
691 if(&agent->nodes == queue)
692 break;
693
694 node = (ecn_node_agent_t *)cast_obj(queue);
695 if (node->timer != 0)
696 continue;
697
698 switch (node->state) {
699 case ecn_node_state_start:
700 ecn_node_timeout_on_start(svc, node);
701 break;
702 case ecn_node_state_set_prpmap_wait:
703 ecn_node_timeout_on_set_prpmap_wait(svc, node);
704 break;
705 case ecn_node_state_get_prpmap_wait:
706 ecn_node_timeout_on_get_prpmap_wait(svc, node);
707 break;
708 case ecn_node_state_anno_prpmap_wait:
709 ecn_node_timeout_on_anno_prpmap_wait(svc, node);
710 break;
711 case ecn_node_state_fault:
712 ecn_node_timeout_on_start(svc, node);
713 break;
714 default:
715#ifdef _DEBUG
716 assert(0);
717#endif
718 break;
719 }
720 }
721}
722
723bool_t ecn_agent_proc_int_msg(ecnl_svc_task_t *svc, ECN_FBS_ID fbs, uint8_t cmd)
724{
725 ecn_agent_t *agent = &svc->agent;
726
727 switch(cmd)
728 {
729 case ECN_INM_GET_DEVICE_LIST_REQ:
730 ecn_agent_proc_get_device_list(svc, agent, fbs);
731 break;
732 case ECN_INM_GET_DEVICE_INFO_REQ:
733 ecn_agent_proc_get_device_info(svc, agent, fbs);
734 break;
735 default:
736 return false;
737 }
738
739 return true;
740}
741
742void ecn_agent_proc_ecn_msg(ecnl_svc_task_t *svc, const EOBJCB **ppk_snod, const EOBJINIB **ppk_sobj, T_EDATA *esv)
743{
744 ecn_agent_t *agent = &svc->agent;
745 ecn_node_agent_t *snod;
746 ecn_obj_t *sobj;
747
748 /* 静的に定義された送信元の場合 */
749 if ((*ppk_snod != NULL) && (*ppk_snod)->eobjs != NULL) {
750 /* 処理しない */
751 return;
752 }
753
754 snod = ecn_agent_find_node2(svc, *ppk_snod);
755
756 /* 送信元を知らなかったら */
757 if (snod == NULL) {
758 /* 送信元のノード情報を新規に作成 */
759 snod = ecn_agent_create_node(svc, agent, esv);
760 if (snod == NULL)
761 return;
762 }
763
764 sobj = ecn_agent_find_obj2(snod, *ppk_sobj);
765
766 /* ノードプロファイルの場合 */
767 if ((esv->hdr.edata.seoj.eojx1 == EOJ_X1_PROFILE)
768 && (esv->hdr.edata.seoj.eojx2 == EOJ_X2_NODE_PROFILE)) {
769 sobj = &snod->node.base;
770 }
771 /* 機器オブジェクトの場合 */
772 else {
773 sobj = ecn_agent_find_eobj(&snod->node.eobj, esv->hdr.edata.seoj);
774 }
775
776 *ppk_snod = &snod->node.eobj;
777 *ppk_sobj = &sobj->inib;
778
779 agent->current_node = snod;
780 agent->msg_proced = false;
781}
782
783void ecn_agent_proc_ecn_msg_end(ecnl_svc_task_t *svc)
784{
785 ecn_agent_t *agent = &svc->agent;
786 ecn_node_agent_t *node = agent->current_node;
787 ecn_obj_t *sobj;
788
789 if(node == NULL)
790 return;
791
792 sobj = node->current;
793 if(sobj == NULL)
794 return;
795
796 if (agent->msg_proced) {
797 switch (node->state) {
798 case ecn_node_state_set_prpmap_wait:
799 ecn_node_next_proc_on_set_prpmap_wait(svc, node, sobj);
800 break;
801 case ecn_node_state_get_prpmap_wait:
802 ecn_node_next_proc_on_get_prpmap_wait(svc, node, sobj);
803 break;
804 case ecn_node_state_anno_prpmap_wait:
805 ecn_node_next_proc_on_anno_prpmap_wait(svc, node, sobj);
806 break;
807 }
808 }
809}
810
811static void ecn_node_send_set_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
812{
813 T_EDATA *esv;
814 ecn_obj_t *obj = node->current;
815
816 // プロパティ値読み出し要求
817 ecn_esv_get(svc, &esv, obj->eobjId, 0x9E);
818 ecn_snd_esv(svc, esv);
819
820 node->state = ecn_node_state_set_prpmap_wait;
821 node->timer = (TMO)5000;
822}
823
824static void ecn_node_send_get_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
825{
826 T_EDATA *esv;
827 ecn_obj_t *obj = node->current;
828
829 // プロパティ値読み出し要求
830 ecn_esv_get(svc, &esv, obj->eobjId, 0x9F);
831 ecn_snd_esv(svc, esv);
832
833 node->state = ecn_node_state_get_prpmap_wait;
834 node->timer = (TMO)5000;
835}
836
837static void ecn_node_send_anno_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
838{
839 T_EDATA *esv;
840 ecn_obj_t *obj = node->current;
841
842 // プロパティ値読み出し要求
843 ecn_esv_get(svc, &esv, obj->eobjId, 0x9D);
844 ecn_snd_esv(svc, esv);
845
846 node->state = ecn_node_state_anno_prpmap_wait;
847 node->timer = (TMO)5000;
848}
849
850static void ecn_node_next_obj(ecn_node_agent_t *node)
851{
852 ecn_obj_t *obj = node->current;
853 ecn_agent_queue_t *queue;
854 ecn_device_t *device;
855
856 /* objが指定されていない場合 */
857 if(obj == NULL){
858 /* このノードを返す */
859 node->current = &node->node.base;
860 return;
861 }
862 /* ノードの場合 */
863 else if((obj->inib.eojx1 == EOJ_X1_PROFILE) && (obj->inib.eojx2 == EOJ_X2_NODE_PROFILE)){
864 node = (ecn_node_agent_t *)obj;
865
866 /* 配下の機器を返す */
867 queue = node->node.devices.p_next;
868 device = (ecn_device_t *)cast_obj(queue);
869 }
870 /* 機器の場合 */
871 else{
872 /* 次の機器を返す */
873 node = (ecn_node_agent_t *)((ecn_device_t *)obj)->node;
874 queue = cast_queue(obj)->p_next;
875 device = (ecn_device_t *)cast_obj(queue);
876 }
877
878 /* その機器が末尾だった場合 */
879 if(&node->node.devices == queue){
880 node->current = NULL;
881 }
882 else {
883 node->current = &device->base;
884 }
885}
886
887static void ecn_node_timeout_on_start(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
888{
889 for (;;) {
890 ecn_obj_t *obj = node->current;
891 if (obj == NULL) {
892 node->state = ecn_node_state_idle;
893 node->timer = TMO_FEVR;
894 return;
895 }
896
897 if((obj->pmapFlag & PMAP_FLAG_SET) == 0){
898 ecn_node_send_set_prop_map(svc, node);
899 break;
900 }
901 else if((obj->pmapFlag & PMAP_FLAG_GET) == 0){
902 ecn_node_send_get_prop_map(svc, node);
903 break;
904 }
905 else if((obj->pmapFlag & PMAP_FLAG_ANNO) == 0){
906 ecn_node_send_anno_prop_map(svc, node);
907 break;
908 }
909 else{
910 ecn_node_next_obj(node);
911 }
912 }
913}
914
915static void ecn_node_next_proc_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj)
916{
917 if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
918 ecn_node_send_get_prop_map(svc, node);
919 }
920 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
921 ecn_node_send_anno_prop_map(svc, node);
922 }
923 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
924 ecn_node_send_set_prop_map(svc, node);
925 }
926 else{
927 ecn_node_next_obj(node);
928 ecn_node_timeout_on_start(svc, node);
929 }
930}
931
932static void ecn_node_timeout_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
933{
934 ecn_obj_t *obj = node->current;
935 if(obj == NULL){
936 node->state = ecn_node_state_idle;
937 node->timer = TMO_FEVR;
938 return;
939 }
940
941 node->retry++;
942 if(node->retry < 3){
943 ecn_node_next_proc_on_set_prpmap_wait(svc, node, obj);
944 }
945 else{
946 node->retry = 0;
947 node->state = ecn_node_state_fault;
948 node->timer = TMO_FEVR;
949 }
950}
951
952static void ecn_node_next_proc_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj)
953{
954 if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
955 ecn_node_send_anno_prop_map(svc, node);
956 }
957 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
958 ecn_node_send_set_prop_map(svc, node);
959 }
960 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
961 ecn_node_send_get_prop_map(svc, node);
962 }
963 else{
964 ecn_node_next_obj(node);
965 ecn_node_timeout_on_start(svc, node);
966 }
967}
968
969static void ecn_node_timeout_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
970{
971 ecn_obj_t *obj = node->current;
972 if(obj == NULL){
973 node->state = ecn_node_state_idle;
974 node->timer = TMO_FEVR;
975 return;
976 }
977
978 ecn_node_next_proc_on_get_prpmap_wait(svc, node, obj);
979}
980
981static void ecn_node_next_proc_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj)
982{
983 if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
984 ecn_node_send_set_prop_map(svc, node);
985 }
986 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
987 ecn_node_send_get_prop_map(svc, node);
988 }
989 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
990 ecn_node_send_anno_prop_map(svc, node);
991 }
992 else{
993 ecn_node_next_obj(node);
994 ecn_node_timeout_on_start(svc, node);
995 }
996}
997
998static void ecn_node_timeout_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
999{
1000 ecn_obj_t *obj = node->current;
1001 if(obj == NULL){
1002 node->state = ecn_node_state_idle;
1003 node->timer = TMO_FEVR;
1004 return;
1005 }
1006
1007 ecn_node_next_proc_on_anno_prpmap_wait(svc, node, obj);
1008}
1009
1010const EPRPINIB *ecn_agent_get_property(const EOBJINIB *fp_obj, uint8_t fa_epc, const EPRPINIB *item)
1011{
1012 ecn_obj_t *obj = cast_obj2(fp_obj);
1013 bool_t has = false;
1014
1015 /* ノードの場合はインスタンスリスト通知と自ノードインスタンスリストS通知を必須で受け取る */
1016 if ((fp_obj->enodid == 0) && ((fa_epc == 0xD5) || (fa_epc == 0xD6)))
1017 has = true;
1018 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapGet))
1019 has = true;
1020 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapSet))
1021 has = true;
1022 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapAnno))
1023 has = true;
1024
1025 if(!has)
1026 return NULL;
1027
1028 ((EPRPINIB *)item)->eprpcd = fa_epc;
1029 ((EPRPINIB *)item)->exinf = (intptr_t)fp_obj;
1030
1031 return item;
1032}
1033
1034int ecn_agent_eprpget(ecnl_svc_task_t *svc, const EPRPINIB *item, void *dst, int size)
1035{
1036 return 0;
1037}
1038
1039int ecn_agent_eprpset(ecnl_svc_task_t *svc, const EPRPINIB *item, const void *src, int size, bool_t *anno)
1040{
1041 ecn_agent_t *agent = cast_agent(item);
1042 ecn_node_agent_t *node = agent->current_node;
1043 const uint8_t *edt = (const uint8_t *)src;
1044 ecn_obj_t *sobj = cast_obj2((const EOBJINIB *)item->exinf);
1045 uint8_t eprpcnt;
1046 int i;
1047
1048 switch (item->eprpcd) {
1049 /* インスタンスリスト通知の場合 */
1050 case 0xD5:
1051 /* 自ノードインスタンスリストS通知の場合 */
1052 case 0xD6:
1053 if ((node != NULL) && (node->state == ecn_node_state_idle)) {
1054 ecn_agent_queue_t *devices = &node->node.devices;
1055 ecn_agent_queue_t *queue = devices->p_next;
1056#ifdef _DEBUG
1057 assert(queue->p_parent == devices);
1058#endif
1059 for (; queue != devices; queue = queue->p_next) {
1060 ecn_obj_t *obj = cast_obj(queue);
1061 obj->pmapFlag = 0;
1062 }
1063 node->node.base.pmapFlag = 0;
1064 node->state = ecn_node_state_start;
1065 node->timer = (TMO)1000;
1066 node->current = sobj;
1067 }
1068 break;
1069 /* 通知プロパティマップの場合 */
1070 case 0x9D:
1071 eprpcnt = edt[0];
1072
1073 if (eprpcnt < 16) {
1074 /* サイズチェック */
1075 if (eprpcnt + 1 != size)
1076 return 0;
1077
1078 for (i = 1; i < size; i++)
1079 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapAnno);
1080 }
1081 else {
1082 /* サイズチェック */
1083 if (size != 17)
1084 return 0;
1085
1086 memcpy(sobj->pmapAnno, &edt[1], 16);
1087 }
1088 sobj->eprpcnt = eprpcnt;
1089 sobj->pmapFlag |= PMAP_FLAG_ANNO;
1090 break;
1091 /* SETプロパティマップの場合 */
1092 case 0x9E:
1093 eprpcnt = edt[0];
1094
1095 if (eprpcnt < 16) {
1096 /* サイズチェック */
1097 if (eprpcnt + 1 != size)
1098 return 0;
1099
1100 for (i = 1; i < size; i++)
1101 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapSet);
1102 }
1103 else {
1104 /* サイズチェック */
1105 if (size != 17)
1106 return 0;
1107
1108 memcpy(sobj->pmapSet, &edt[1], 16);
1109 }
1110 sobj->eprpcnt = eprpcnt;
1111 sobj->pmapFlag |= PMAP_FLAG_SET;
1112 break;
1113 /* GETプロパティマップの場合 */
1114 case 0x9F:
1115 eprpcnt = edt[0];
1116
1117 if (eprpcnt < 16) {
1118 /* サイズチェック */
1119 if (eprpcnt + 1 != size)
1120 return 0;
1121
1122 for (i = 1; i < size; i++)
1123 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapGet);
1124 }
1125 else {
1126 /* サイズチェック */
1127 if (size != 17)
1128 return 0;
1129
1130 memcpy(sobj->pmapGet, &edt[1], 16);
1131 }
1132 sobj->eprpcnt = eprpcnt;
1133 sobj->pmapFlag |= PMAP_FLAG_GET;
1134 break;
1135 default:
1136 svc->forward_esv = true;
1137 return 0;
1138 }
1139
1140 agent->msg_proced = true;
1141
1142 return size;
1143}
1144
1145ER ecn_agent_get_device_list(ecnl_svc_task_t *svc, T_ECN_FBS_QUEUE *sender, int requestid, ECN_FBS_ID *pk_req)
1146{
1147 mrb_state *mrb = svc->mrb;
1148 ER a_ret;
1149 ECN_FBS_ID req;
1150
1151 a_ret = _ecn_tsk_cre_req_fbs(svc, sender, ECN_INM_GET_DEVICE_LIST_REQ, &req);
1152 if (a_ret != E_OK) {
1153 return a_ret;
1154 }
1155
1156 a_ret = _ecn_fbs_add_data_ex(mrb, req, &requestid, sizeof(((ecn_inm_get_device_list_req_t *)0)->requestid));
1157 if (a_ret != E_OK) {
1158 _ecn_fbs_del(mrb, req);
1159 return a_ret;
1160 }
1161
1162 *pk_req = req;
1163
1164 return E_OK;
1165}
1166
1167ER ecn_agent_get_device_info(ecnl_svc_task_t *svc, T_ECN_FBS_QUEUE *sender, int requestid, ID eobjid, ECN_FBS_ID *pk_req)
1168{
1169 mrb_state *mrb = svc->mrb;
1170 ER a_ret;
1171 ECN_FBS_ID req;
1172
1173 a_ret = _ecn_tsk_cre_req_fbs(svc, sender, ECN_INM_GET_DEVICE_INFO_REQ, &req);
1174 if (a_ret != E_OK) {
1175 return a_ret;
1176 }
1177
1178 a_ret = _ecn_fbs_add_data_ex(mrb, req, &requestid, sizeof(((ecn_inm_get_device_info_req_t *)0)->requestid));
1179 if (a_ret != E_OK) {
1180 _ecn_fbs_del(mrb, req);
1181 return a_ret;
1182 }
1183
1184 a_ret = _ecn_fbs_add_data_ex(mrb, req, &eobjid, sizeof(((ecn_inm_get_device_info_req_t *)0)->eobjid));
1185 if (a_ret != E_OK) {
1186 _ecn_fbs_del(mrb, req);
1187 return a_ret;
1188 }
1189
1190 *pk_req = req;
1191
1192 return E_OK;
1193}
Note: See TracBrowser for help on using the repository browser.