svghmi/svghmi.c
branchRuntimeLists
changeset 3400 c2b46d0965ca
parent 3399 95e0b926a8c3
child 3613 7af7a23e4adb
equal deleted inserted replaced
3399:95e0b926a8c3 3400:c2b46d0965ca
    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     }
   345     SVGHMI_SuspendFromPythonThread();
   345     SVGHMI_SuspendFromPythonThread();
   346 }
   346 }
   347 
   347 
   348 int svghmi_send_collect(uint32_t session_index, uint32_t *size, char **ptr){
   348 int svghmi_send_collect(uint32_t session_index, uint32_t *size, char **ptr){
   349 
   349 
       
   350 
   350     if(svghmi_continue_collect) {
   351     if(svghmi_continue_collect) {
   351         int res;
   352         int res;
   352         sbufidx = HMI_HASH_SIZE;
   353         sbufidx = HMI_HASH_SIZE;
   353 
   354 
   354         while(AtomicCompareExchange(&hmitree_wlock, 0, 1)){
   355         while(AtomicCompareExchange(&hmitree_wlock, 0, 1)){
   356         }
   357         }
   357 
   358 
   358         hmi_tree_item_t *dsc = subscriptions_tail;
   359         hmi_tree_item_t *dsc = subscriptions_tail;
   359         while(dsc){
   360         while(dsc){
   360             uint32_t index = dsc - hmi_tree_items;
   361             uint32_t index = dsc - hmi_tree_items;
   361             printf("Send index %%d\n", index);
       
   362             res = send_iterator(index, dsc, session_index);
   362             res = send_iterator(index, dsc, session_index);
   363             if(res != 0){
   363             if(res != 0){
   364                 break;
   364                 break;
   365             }
   365             }
   366             dsc = dsc->subscriptions_prev;
   366             dsc = dsc->subscriptions_prev;
   375                 return 0;
   375                 return 0;
   376             }
   376             }
   377             AtomicCompareExchange(&hmitree_wlock, 1, 0);
   377             AtomicCompareExchange(&hmitree_wlock, 1, 0);
   378             return ENODATA;
   378             return ENODATA;
   379         }
   379         }
   380         // printf("collected BAD result %%d\n", res);
       
   381         AtomicCompareExchange(&hmitree_wlock, 1, 0);
   380         AtomicCompareExchange(&hmitree_wlock, 1, 0);
   382         return res;
   381         return res;
   383     }
   382     }
   384     else
   383     else
   385     {
   384     {
   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
   428     {
   432     {
   429         uint32_t progress;
   433         uint32_t progress;
   430 
   434 
   431         cmd_old = cmd;
   435         cmd_old = cmd;
   432         cmd = *(cursor++);
   436         cmd = *(cursor++);
       
   437 
   433 
   438 
   434         if(cmd_old != cmd){
   439         if(cmd_old != cmd){
   435             if(got_wlock){
   440             if(got_wlock){
   436                 AtomicCompareExchange(&hmitree_wlock, 1, 0);
   441                 AtomicCompareExchange(&hmitree_wlock, 1, 0);
   437                 got_wlock = 0;
   442                 got_wlock = 0;
   445         {
   450         {
   446             case setval:
   451             case setval:
   447             {
   452             {
   448                 uint32_t index = *(uint32_t*)(cursor);
   453                 uint32_t index = *(uint32_t*)(cursor);
   449                 uint8_t const *valptr = cursor + sizeof(uint32_t);
   454                 uint8_t const *valptr = cursor + sizeof(uint32_t);
       
   455 
   450 
   456 
   451                 if(index == heartbeat_index)
   457                 if(index == heartbeat_index)
   452                     was_hearbeat = 1;
   458                     was_hearbeat = 1;
   453 
   459 
   454                 if(index < HMI_ITEM_COUNT)
   460                 if(index < HMI_ITEM_COUNT)
   509                     got_wlock = 1;
   515                     got_wlock = 1;
   510                 }
   516                 }
   511                 {
   517                 {
   512                     hmi_tree_item_t *dsc = subscriptions_tail;
   518                     hmi_tree_item_t *dsc = subscriptions_tail;
   513                     while(dsc){
   519                     while(dsc){
       
   520                         hmi_tree_item_t *_dsc = dsc->subscriptions_prev;
   514                         update_refresh_period(dsc, session_index, 0);
   521                         update_refresh_period(dsc, session_index, 0);
   515                         dsc = dsc->subscriptions_prev;
   522                         dsc = _dsc;
   516                     }
   523                     }
   517                 }
   524                 }
   518             }
   525             }
   519             break;
   526             break;
   520 
   527