svghmi/svghmi.c
branchsvghmi
changeset 3270 38f7122ccbf9
parent 2863 e120d6985a2f
child 3271 561dbd1e3e04
equal deleted inserted replaced
3269:5d174cdf4d98 3270:38f7122ccbf9
     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 
    43     __IEC_types_enum type;
    45     __IEC_types_enum type;
    44     uint32_t buf_index;
    46     uint32_t buf_index;
    45 
    47 
    46     /* publish/write/send */
    48     /* publish/write/send */
    47     long wlock;
    49     long wlock;
    48     buf_state_t wstate;
    50     buf_state_t wstate[MAX_CONNECTIONS];
    49 
    51 
    50     /* zero means not subscribed */
    52     /* zero means not subscribed */
    51     uint16_t refresh_period_ms;
    53     uint16_t refresh_period_ms[MAX_CONNECTIONS];
    52     uint16_t age_ms;
    54     uint16_t age_ms[MAX_CONNECTIONS];
    53 
    55 
    54     /* retrieve/read/recv */
    56     /* retrieve/read/recv */
    55     long rlock;
    57     long rlock;
    56     buf_state_t rstate;
    58     buf_state_t rstate;
    57 
    59 
    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 
   334             break;
   341             break;
   335 
   342 
   336             case reset:
   343             case reset:
   337             {
   344             {
   338                 progress = 0;
   345                 progress = 0;
       
   346                 reset_session_index = session_index;
   339                 traverse_hmi_tree(reset_iterator);
   347                 traverse_hmi_tree(reset_iterator);
   340             }
   348             }
   341             break;
   349             break;
   342 
   350 
   343             case subscribe:
   351             case subscribe:
   346                 uint16_t refresh_period_ms = *(uint32_t*)(cursor + sizeof(uint32_t));
   354                 uint16_t refresh_period_ms = *(uint32_t*)(cursor + sizeof(uint32_t));
   347 
   355 
   348                 if(index < HMI_ITEM_COUNT)
   356                 if(index < HMI_ITEM_COUNT)
   349                 {
   357                 {
   350                     hmi_tree_item_t *dsc = &hmi_tree_item[index];
   358                     hmi_tree_item_t *dsc = &hmi_tree_item[index];
   351                     update_refresh_period(dsc, refresh_period_ms);
   359                     update_refresh_period(dsc, session_index, refresh_period_ms);
   352                 }
   360                 }
   353                 else
   361                 else
   354                 {
   362                 {
   355                     return -EINVAL;
   363                     return -EINVAL;
   356                 }
   364                 }