7 |
7 |
8 #define DEFAULT_REFRESH_PERIOD_MS 100 |
8 #define DEFAULT_REFRESH_PERIOD_MS 100 |
9 #define HMI_BUFFER_SIZE %(buffer_size)d |
9 #define HMI_BUFFER_SIZE %(buffer_size)d |
10 #define HMI_ITEM_COUNT %(item_count)d |
10 #define HMI_ITEM_COUNT %(item_count)d |
11 #define HMI_HASH_SIZE 8 |
11 #define HMI_HASH_SIZE 8 |
|
12 #define MAX_CONNECTIONS %(max_connections)d |
|
13 |
12 static uint8_t hmi_hash[HMI_HASH_SIZE] = {%(hmi_hash_ints)s}; |
14 static uint8_t hmi_hash[HMI_HASH_SIZE] = {%(hmi_hash_ints)s}; |
13 |
15 |
14 /* PLC reads from that buffer */ |
16 /* PLC reads from that buffer */ |
15 static char rbuf[HMI_BUFFER_SIZE]; |
17 static char rbuf[HMI_BUFFER_SIZE]; |
16 |
18 |
79 |
81 |
80 %(var_access_code)s |
82 %(var_access_code)s |
81 |
83 |
82 static int write_iterator(uint32_t index, hmi_tree_item_t *dsc) |
84 static int write_iterator(uint32_t index, hmi_tree_item_t *dsc) |
83 { |
85 { |
84 if(AtomicCompareExchange(&dsc->wlock, 0, 1) == 0) |
86 uint32_t session_index = 0; |
85 { |
87 if(AtomicCompareExchange(&dsc->wlock, 0, 1) == 0) while(session_index < MAX_CONNECTIONS) |
86 if(dsc->wstate == buf_set){ |
88 { |
|
89 if(dsc->wstate[session_index] == buf_set){ |
87 /* if being subscribed */ |
90 /* if being subscribed */ |
88 if(dsc->refresh_period_ms){ |
91 if(dsc->refresh_period_ms[session_index]){ |
89 if(dsc->age_ms + ticktime_ms < dsc->refresh_period_ms){ |
92 if(dsc->age_ms[session_index] + ticktime_ms < dsc->refresh_period_ms[session_index]){ |
90 dsc->age_ms += ticktime_ms; |
93 dsc->age_ms[session_index] += ticktime_ms; |
91 }else{ |
94 }else{ |
92 dsc->wstate = buf_tosend; |
95 dsc->wstate[session_index] = buf_tosend; |
93 global_write_dirty = 1; |
96 global_write_dirty = 1; |
94 } |
97 } |
95 } |
98 } |
96 } |
99 } |
97 |
100 |
103 /* if new value differs from previous one */ |
106 /* if new value differs from previous one */ |
104 USINT sz = __get_type_enum_size(dsc->type); |
107 USINT sz = __get_type_enum_size(dsc->type); |
105 if(__Is_a_string(dsc)){ |
108 if(__Is_a_string(dsc)){ |
106 sz = ((STRING*)visible_value_p)->len + 1; |
109 sz = ((STRING*)visible_value_p)->len + 1; |
107 } |
110 } |
108 if(dsc->wstate == buf_new /* just subscribed |
111 if(dsc->wstate[session_index] == buf_new /* just subscribed |
109 or already subscribed having value change */ |
112 or already subscribed having value change */ |
110 || (dsc->refresh_period_ms > 0 && memcmp(dest_p, visible_value_p, sz) != 0)){ |
113 || (dsc->refresh_period_ms[session_index] > 0 && memcmp(dest_p, visible_value_p, sz) != 0)){ |
111 /* copy and flag as set */ |
114 /* copy and flag as set */ |
112 memcpy(dest_p, visible_value_p, sz); |
115 memcpy(dest_p, visible_value_p, sz); |
113 /* if not already marked/signaled, do it */ |
116 /* if not already marked/signaled, do it */ |
114 if(dsc->wstate != buf_set && dsc->wstate != buf_tosend) { |
117 if(dsc->wstate[session_index] != buf_set && dsc->wstate[session_index] != buf_tosend) { |
115 if(dsc->wstate == buf_new || ticktime_ms > dsc->refresh_period_ms){ |
118 if(dsc->wstate[session_index] == buf_new || ticktime_ms > dsc->refresh_period_ms[session_index]){ |
116 dsc->wstate = buf_tosend; |
119 dsc->wstate[session_index] = buf_tosend; |
117 global_write_dirty = 1; |
120 global_write_dirty = 1; |
118 } else { |
121 } else { |
119 dsc->wstate = buf_set; |
122 dsc->wstate[session_index] = buf_set; |
120 } |
123 } |
121 dsc->age_ms = 0; |
124 dsc->age_ms[session_index] = 0; |
122 } |
125 } |
123 } |
126 } |
124 |
127 |
125 AtomicCompareExchange(&dsc->wlock, 1, 0); |
128 AtomicCompareExchange(&dsc->wlock, 1, 0); |
|
129 session_index++; |
126 } |
130 } |
127 // else ... : PLC can't wait, variable will be updated next turn |
131 // else ... : PLC can't wait, variable will be updated next turn |
128 return 0; |
132 return 0; |
129 } |
133 } |
130 |
134 |
|
135 static uint32_t send_session_index; |
131 static int send_iterator(uint32_t index, hmi_tree_item_t *dsc) |
136 static int send_iterator(uint32_t index, hmi_tree_item_t *dsc) |
132 { |
137 { |
133 while(AtomicCompareExchange(&dsc->wlock, 0, 1)) sched_yield(); |
138 while(AtomicCompareExchange(&dsc->wlock, 0, 1)) sched_yield(); |
134 |
139 |
135 if(dsc->wstate == buf_tosend) |
140 if(dsc->wstate[send_session_index] == buf_tosend) |
136 { |
141 { |
137 uint32_t sz = __get_type_enum_size(dsc->type); |
142 uint32_t sz = __get_type_enum_size(dsc->type); |
138 if(sbufidx + sizeof(uint32_t) + sz <= sizeof(sbuf)) |
143 if(sbufidx + sizeof(uint32_t) + sz <= sizeof(sbuf)) |
139 { |
144 { |
140 void *src_p = &wbuf[dsc->buf_index]; |
145 void *src_p = &wbuf[dsc->buf_index]; |
143 sz = ((STRING*)src_p)->len + 1; |
148 sz = ((STRING*)src_p)->len + 1; |
144 } |
149 } |
145 /* TODO : force into little endian */ |
150 /* TODO : force into little endian */ |
146 memcpy(dst_p, &index, sizeof(uint32_t)); |
151 memcpy(dst_p, &index, sizeof(uint32_t)); |
147 memcpy(dst_p + sizeof(uint32_t), src_p, sz); |
152 memcpy(dst_p + sizeof(uint32_t), src_p, sz); |
148 dsc->wstate = buf_free; |
153 dsc->wstate[send_session_index] = buf_free; |
149 sbufidx += sizeof(uint32_t) /* index */ + sz; |
154 sbufidx += sizeof(uint32_t) /* index */ + sz; |
150 } |
155 } |
151 else |
156 else |
152 { |
157 { |
153 printf("BUG!!! %%d + %%ld + %%d > %%ld \n", sbufidx, sizeof(uint32_t), sz, sizeof(sbuf)); |
158 printf("BUG!!! %%d + %%ld + %%d > %%ld \n", sbufidx, sizeof(uint32_t), sz, sizeof(sbuf)); |
177 } |
182 } |
178 // else ... : PLC can't wait, variable will be updated next turn |
183 // else ... : PLC can't wait, variable will be updated next turn |
179 return 0; |
184 return 0; |
180 } |
185 } |
181 |
186 |
182 void update_refresh_period(hmi_tree_item_t *dsc, uint16_t refresh_period_ms) |
187 void update_refresh_period(hmi_tree_item_t *dsc, uint32_t session_index, uint16_t refresh_period_ms) |
183 { |
188 { |
184 while(AtomicCompareExchange(&dsc->wlock, 0, 1)) sched_yield(); |
189 while(AtomicCompareExchange(&dsc->wlock, 0, 1)) sched_yield(); |
185 if(refresh_period_ms) { |
190 if(refresh_period_ms) { |
186 if(!dsc->refresh_period_ms) |
191 if(!dsc->refresh_period_ms[session_index]) |
187 { |
192 { |
188 dsc->wstate = buf_new; |
193 dsc->wstate[session_index] = buf_new; |
189 } |
194 } |
190 } else { |
195 } else { |
191 dsc->wstate = buf_free; |
196 dsc->wstate[session_index] = buf_free; |
192 } |
197 } |
193 dsc->refresh_period_ms = refresh_period_ms; |
198 dsc->refresh_period_ms[session_index] = refresh_period_ms; |
194 AtomicCompareExchange(&dsc->wlock, 1, 0); |
199 AtomicCompareExchange(&dsc->wlock, 1, 0); |
195 } |
200 } |
196 |
201 |
|
202 static uint32_t reset_session_index; |
197 static int reset_iterator(uint32_t index, hmi_tree_item_t *dsc) |
203 static int reset_iterator(uint32_t index, hmi_tree_item_t *dsc) |
198 { |
204 { |
199 update_refresh_period(dsc, 0); |
205 update_refresh_period(dsc, reset_session_index, 0); |
200 return 0; |
206 return 0; |
201 } |
207 } |
202 |
208 |
203 void SVGHMI_SuspendFromPythonThread(void); |
209 void SVGHMI_SuspendFromPythonThread(void); |
204 void SVGHMI_WakeupFromRTThread(void); |
210 void SVGHMI_WakeupFromRTThread(void); |
234 SVGHMI_WakeupFromRTThread(); |
240 SVGHMI_WakeupFromRTThread(); |
235 } |
241 } |
236 } |
242 } |
237 |
243 |
238 /* PYTHON CALLS */ |
244 /* PYTHON CALLS */ |
239 int svghmi_send_collect(uint32_t *size, char **ptr){ |
245 int svghmi_send_collect(uint32_t session_index, uint32_t *size, char **ptr){ |
240 |
246 |
241 SVGHMI_SuspendFromPythonThread(); |
247 SVGHMI_SuspendFromPythonThread(); |
242 |
248 |
243 if(continue_collect) { |
249 if(continue_collect) { |
244 int res; |
250 int res; |
245 sbufidx = HMI_HASH_SIZE; |
251 sbufidx = HMI_HASH_SIZE; |
|
252 send_session_index = session_index; |
246 if((res = traverse_hmi_tree(send_iterator)) == 0) |
253 if((res = traverse_hmi_tree(send_iterator)) == 0) |
247 { |
254 { |
248 if(sbufidx > HMI_HASH_SIZE){ |
255 if(sbufidx > HMI_HASH_SIZE){ |
249 memcpy(&sbuf[0], &hmi_hash[0], HMI_HASH_SIZE); |
256 memcpy(&sbuf[0], &hmi_hash[0], HMI_HASH_SIZE); |
250 *ptr = &sbuf[0]; |
257 *ptr = &sbuf[0]; |
268 subscribe = 2 |
275 subscribe = 2 |
269 } cmd_from_JS; |
276 } cmd_from_JS; |
270 |
277 |
271 // Returns : |
278 // Returns : |
272 // 0 is OK, <0 is error, 1 is heartbeat |
279 // 0 is OK, <0 is error, 1 is heartbeat |
273 int svghmi_recv_dispatch(uint32_t size, const uint8_t *ptr){ |
280 int svghmi_recv_dispatch(uint32_t session_index, uint32_t size, const uint8_t *ptr){ |
274 const uint8_t* cursor = ptr + HMI_HASH_SIZE; |
281 const uint8_t* cursor = ptr + HMI_HASH_SIZE; |
275 const uint8_t* end = ptr + size; |
282 const uint8_t* end = ptr + size; |
276 |
283 |
277 int was_hearbeat = 0; |
284 int was_hearbeat = 0; |
278 |
285 |