96 |
96 |
97 %(var_access_code)s |
97 %(var_access_code)s |
98 |
98 |
99 static int write_iterator(hmi_tree_item_t *dsc) |
99 static int write_iterator(hmi_tree_item_t *dsc) |
100 { |
100 { |
101 { |
101 uint32_t session_index = 0; |
102 uint32_t session_index = 0; |
102 int value_changed = 0; |
103 int value_changed = 0; |
103 void *dest_p = NULL; |
104 void *dest_p = NULL; |
104 void *value_p = NULL; |
105 void *value_p = NULL; |
105 size_t sz = 0; |
106 size_t sz = 0; |
106 while(session_index < MAX_CONNECTIONS) { |
107 while(session_index < MAX_CONNECTIONS) { |
107 if(dsc->wstate[session_index] == buf_set){ |
108 if(dsc->wstate[session_index] == buf_set){ |
108 /* if being subscribed */ |
109 /* if being subscribed */ |
109 if(dsc->refresh_period_ms[session_index]){ |
110 if(dsc->refresh_period_ms[session_index]){ |
110 if(dsc->age_ms[session_index] + ticktime_ms < dsc->refresh_period_ms[session_index]){ |
111 if(dsc->age_ms[session_index] + ticktime_ms < dsc->refresh_period_ms[session_index]){ |
111 dsc->age_ms[session_index] += ticktime_ms; |
112 dsc->age_ms[session_index] += ticktime_ms; |
112 }else{ |
113 }else{ |
113 dsc->wstate[session_index] = buf_tosend; |
114 dsc->wstate[session_index] = buf_tosend; |
114 global_write_dirty = 1; |
115 global_write_dirty = 1; |
115 } |
116 } |
116 } |
117 } |
117 } |
118 } |
118 |
119 |
119 /* variable is sample only if just subscribed |
120 /* variable is sample only if just subscribed |
120 or already subscribed and having value change */ |
121 or already subscribed and having value change */ |
121 int do_sample = 0; |
122 int do_sample = 0; |
122 int just_subscribed = dsc->wstate[session_index] == buf_new; |
123 int just_subscribed = dsc->wstate[session_index] == buf_new; |
123 if(!just_subscribed){ |
124 if(!just_subscribed){ |
124 int already_subscribed = dsc->refresh_period_ms[session_index] > 0; |
125 int already_subscribed = dsc->refresh_period_ms[session_index] > 0; |
125 if(already_subscribed){ |
126 if(already_subscribed){ |
126 if(!value_changed){ |
127 if(!value_changed){ |
127 if(!value_p){ |
128 if(!value_p){ |
128 UnpackVar(dsc, &value_p, NULL, &sz); |
129 UnpackVar(dsc, &value_p, NULL, &sz); |
129 if(__Is_a_string(dsc)){ |
130 if(__Is_a_string(dsc)){ |
130 sz = ((STRING*)value_p)->len + 1; |
131 sz = ((STRING*)value_p)->len + 1; |
|
132 } |
|
133 dest_p = &wbuf[dsc->buf_index]; |
|
134 } |
131 } |
135 value_changed = memcmp(dest_p, value_p, sz) != 0; |
132 dest_p = &wbuf[dsc->buf_index]; |
136 do_sample = value_changed; |
133 } |
137 }else{ |
134 value_changed = memcmp(dest_p, value_p, sz) != 0; |
138 do_sample = 1; |
135 do_sample = value_changed; |
139 } |
136 }else{ |
140 } |
137 do_sample = 1; |
141 } else { |
138 } |
142 do_sample = 1; |
139 } |
143 } |
140 } else { |
144 |
141 do_sample = 1; |
145 |
142 } |
146 if(do_sample){ |
143 |
147 if(dsc->wstate[session_index] != buf_set && dsc->wstate[session_index] != buf_tosend) { |
144 |
148 if(dsc->wstate[session_index] == buf_new \ |
145 if(do_sample){ |
149 || ticktime_ms > dsc->refresh_period_ms[session_index]){ |
146 if(dsc->wstate[session_index] != buf_set && dsc->wstate[session_index] != buf_tosend) { |
150 dsc->wstate[session_index] = buf_tosend; |
147 if(dsc->wstate[session_index] == buf_new \ |
151 global_write_dirty = 1; |
148 || ticktime_ms > dsc->refresh_period_ms[session_index]){ |
152 } else { |
149 dsc->wstate[session_index] = buf_tosend; |
153 dsc->wstate[session_index] = buf_set; |
150 global_write_dirty = 1; |
154 } |
151 } else { |
155 dsc->age_ms[session_index] = 0; |
152 dsc->wstate[session_index] = buf_set; |
156 } |
153 } |
157 } |
154 dsc->age_ms[session_index] = 0; |
158 |
155 } |
159 session_index++; |
156 } |
160 } |
157 |
161 /* copy value if changed (and subscribed) */ |
158 session_index++; |
162 if(value_changed) |
159 } |
163 memcpy(dest_p, value_p, sz); |
160 /* copy value if changed (and subscribed) */ |
164 } |
161 if(value_changed) |
165 // else ... : PLC can't wait, variable will be updated next turn |
162 memcpy(dest_p, value_p, sz); |
166 return 0; |
163 return 0; |
167 } |
164 } |
168 |
165 |
169 static int send_iterator(uint32_t index, hmi_tree_item_t *dsc, uint32_t session_index) |
166 static int send_iterator(uint32_t index, hmi_tree_item_t *dsc, uint32_t session_index) |
170 { |
167 { |
211 void update_refresh_period(hmi_tree_item_t *dsc, uint32_t session_index, uint16_t refresh_period_ms) |
208 void update_refresh_period(hmi_tree_item_t *dsc, uint32_t session_index, uint16_t refresh_period_ms) |
212 { |
209 { |
213 uint32_t other_session_index = 0; |
210 uint32_t other_session_index = 0; |
214 int previously_subscribed = 0; |
211 int previously_subscribed = 0; |
215 int session_only_subscriber = 0; |
212 int session_only_subscriber = 0; |
216 int session_subscriber = 0; |
213 int session_already_subscriber = 0; |
217 int needs_subscription_for_session = (refresh_period_ms != 0); |
214 int needs_subscription_for_session = (refresh_period_ms != 0); |
218 |
215 |
219 while(other_session_index < session_index) { |
216 while(other_session_index < session_index) { |
220 previously_subscribed |= (dsc->refresh_period_ms[other_session_index++] != 0); |
217 previously_subscribed |= (dsc->refresh_period_ms[other_session_index++] != 0); |
221 } |
218 } |
222 session_subscriber = (dsc->refresh_period_ms[other_session_index++] != 0); |
219 session_already_subscriber = (dsc->refresh_period_ms[other_session_index++] != 0); |
223 while(other_session_index < MAX_CONNECTIONS) { |
220 while(other_session_index < MAX_CONNECTIONS) { |
224 previously_subscribed |= (dsc->refresh_period_ms[other_session_index++] != 0); |
221 previously_subscribed |= (dsc->refresh_period_ms[other_session_index++] != 0); |
225 } |
222 } |
226 session_only_subscriber = session_subscriber && !previously_subscribed; |
223 session_only_subscriber = session_already_subscriber && !previously_subscribed; |
227 previously_subscribed |= session_subscriber; |
224 previously_subscribed |= session_already_subscriber; |
228 |
|
229 printf("update_refresh_period %%x,%%x index:%%d session_index:%%d refresh_period_ms:%%d\n", |
|
230 dsc, |
|
231 hmi_tree_items, |
|
232 dsc - hmi_tree_items, |
|
233 session_index, |
|
234 refresh_period_ms); |
|
235 |
225 |
236 if(needs_subscription_for_session) { |
226 if(needs_subscription_for_session) { |
237 if(!session_subscriber) |
227 if(!session_already_subscriber) |
238 { |
228 { |
239 dsc->wstate[session_index] = buf_new; |
229 dsc->wstate[session_index] = buf_new; |
240 } |
230 } |
241 /* if not already subscribed */ |
231 /* item is appended to list only when no session was previously subscribed */ |
242 if(!previously_subscribed){ |
232 if(!previously_subscribed){ |
243 /* append subsciption to list */ |
233 /* append subsciption to list */ |
|
234 if(subscriptions_tail != NULL){ |
|
235 /* if list wasn't empty, link with previous tail*/ |
|
236 subscriptions_tail->subscriptions_next = dsc; |
|
237 } |
244 dsc->subscriptions_prev = subscriptions_tail; |
238 dsc->subscriptions_prev = subscriptions_tail; |
245 subscriptions_tail = dsc; |
239 subscriptions_tail = dsc; |
246 dsc->subscriptions_next = NULL; |
240 dsc->subscriptions_next = NULL; |
247 } |
241 } |
248 } else { |
242 } else { |
250 /* item is removed from list only when session was the only one remaining */ |
244 /* item is removed from list only when session was the only one remaining */ |
251 if (session_only_subscriber) { |
245 if (session_only_subscriber) { |
252 if(dsc->subscriptions_next == NULL){ /* remove tail */ |
246 if(dsc->subscriptions_next == NULL){ /* remove tail */ |
253 /* re-link tail to previous */ |
247 /* re-link tail to previous */ |
254 subscriptions_tail = dsc->subscriptions_prev; |
248 subscriptions_tail = dsc->subscriptions_prev; |
|
249 if(subscriptions_tail != NULL){ |
|
250 subscriptions_tail->subscriptions_next = NULL; |
|
251 } |
|
252 } else if(dsc->subscriptions_prev == NULL){ /* remove head */ |
|
253 dsc->subscriptions_next->subscriptions_prev = NULL; |
255 } else { /* remove entry in between other entries */ |
254 } else { /* remove entry in between other entries */ |
256 /* re-link previous iand next node */ |
255 /* re-link previous and next node */ |
257 dsc->subscriptions_next->subscriptions_prev = dsc->subscriptions_prev; |
256 dsc->subscriptions_next->subscriptions_prev = dsc->subscriptions_prev; |
258 dsc->subscriptions_prev->subscriptions_next = dsc->subscriptions_next; |
257 dsc->subscriptions_prev->subscriptions_next = dsc->subscriptions_next; |
259 } |
258 } |
260 /* unnecessary |
259 /* unnecessary |
261 dsc->subscriptions_next = NULL; |
260 dsc->subscriptions_next = NULL; |
307 { |
306 { |
308 if(AtomicCompareExchange(&hmitree_rlock, 0, 1) == 0) { |
307 if(AtomicCompareExchange(&hmitree_rlock, 0, 1) == 0) { |
309 hmi_tree_item_t *dsc = incoming_tail; |
308 hmi_tree_item_t *dsc = incoming_tail; |
310 /* iterate through read list (changes from HMI) */ |
309 /* iterate through read list (changes from HMI) */ |
311 while(dsc){ |
310 while(dsc){ |
|
311 hmi_tree_item_t *_dsc = dsc->incoming_prev; |
312 read_iterator(dsc); |
312 read_iterator(dsc); |
313 dsc = dsc->incoming_prev; |
|
314 /* unnecessary |
313 /* unnecessary |
315 dsc->incoming_prev = NULL; |
314 dsc->incoming_prev = NULL; |
316 */ |
315 */ |
|
316 dsc = _dsc; |
317 } |
317 } |
318 /* flush read list */ |
318 /* flush read list */ |
319 incoming_tail = NULL; |
319 incoming_tail = NULL; |
320 AtomicCompareExchange(&hmitree_rlock, 1, 0); |
320 AtomicCompareExchange(&hmitree_rlock, 1, 0); |
321 } |
321 } |
394 subscribe = 2 |
393 subscribe = 2 |
395 } cmd_from_JS; |
394 } cmd_from_JS; |
396 |
395 |
397 int svghmi_reset(uint32_t session_index){ |
396 int svghmi_reset(uint32_t session_index){ |
398 hmi_tree_item_t *dsc = subscriptions_tail; |
397 hmi_tree_item_t *dsc = subscriptions_tail; |
|
398 while(AtomicCompareExchange(&hmitree_wlock, 0, 1)){ |
|
399 nRT_reschedule(); |
|
400 } |
399 while(dsc){ |
401 while(dsc){ |
|
402 hmi_tree_item_t *_dsc = dsc->subscriptions_prev; |
400 update_refresh_period(dsc, session_index, 0); |
403 update_refresh_period(dsc, session_index, 0); |
401 dsc = dsc->subscriptions_prev; |
404 dsc = _dsc; |
402 } |
405 } |
|
406 AtomicCompareExchange(&hmitree_wlock, 1, 0); |
403 return 1; |
407 return 1; |
404 } |
408 } |
405 |
409 |
406 // Returns : |
410 // Returns : |
407 // 0 is OK, <0 is error, 1 is heartbeat |
411 // 0 is OK, <0 is error, 1 is heartbeat |