/* gets the next free invokeID, and reserves a spot in the table returns 0 if none are available */ uint8_t tsm_next_free_invokeID( void) { uint8_t index = 0; uint8_t invokeID = 0; bool found = false; /* is there even space available? */ if (tsm_transaction_available()) { while (!found) { index = tsm_find_invokeID_index(Current_Invoke_ID); if (index == MAX_TSM_TRANSACTIONS) { /* Not found, so this invokeID is not used */ found = true; /* set this id into the table */ index = tsm_find_first_free_index(); if (index != MAX_TSM_TRANSACTIONS) { TSM_List[index].InvokeID = invokeID = Current_Invoke_ID; TSM_List[index].state = TSM_STATE_IDLE; TSM_List[index].RequestTimer = apdu_timeout(); /* update for the next call or check */ Current_Invoke_ID++; /* skip zero - we treat that internally as invalid or no free */ if (Current_Invoke_ID == 0) { Current_Invoke_ID = 1; } } } else { /* found! This invokeID is already used */ /* try next one */ Current_Invoke_ID++; /* skip zero - we treat that internally as invalid or no free */ if (Current_Invoke_ID == 0) { Current_Invoke_ID = 1; } } } } return invokeID; }
void handler_cov_task( void) { static int index = 0; BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE; uint32_t object_instance = 0; bool status = false; bool send = false; BACNET_PROPERTY_VALUE value_list[2]; /* states for transmitting */ static enum { COV_STATE_IDLE = 0, COV_STATE_MARK, COV_STATE_CLEAR, COV_STATE_FREE, COV_STATE_SEND } cov_task_state = COV_STATE_IDLE; switch (cov_task_state) { case COV_STATE_IDLE: index = 0; cov_task_state = COV_STATE_MARK; break; case COV_STATE_MARK: /* mark any subscriptions where the value has changed */ if (COV_Subscriptions[index].flag.valid) { object_type = (BACNET_OBJECT_TYPE) COV_Subscriptions[index].monitoredObjectIdentifier.type; object_instance = COV_Subscriptions[index]. monitoredObjectIdentifier.instance; status = Device_COV(object_type, object_instance); if (status) { COV_Subscriptions[index].flag.send_requested = true; #if PRINT_ENABLED fprintf(stderr, "COVtask: Marking...\n"); #endif } } index++; if (index >= MAX_COV_SUBCRIPTIONS) { index = 0; cov_task_state = COV_STATE_CLEAR; } break; case COV_STATE_CLEAR: /* clear the COV flag after checking all subscriptions */ if ((COV_Subscriptions[index].flag.valid) && (COV_Subscriptions[index].flag.send_requested)) { object_type = (BACNET_OBJECT_TYPE) COV_Subscriptions[index].monitoredObjectIdentifier.type; object_instance = COV_Subscriptions[index]. monitoredObjectIdentifier.instance; Device_COV_Clear(object_type, object_instance); } index++; if (index >= MAX_COV_SUBCRIPTIONS) { index = 0; cov_task_state = COV_STATE_FREE; } break; case COV_STATE_FREE: /* confirmed notification house keeping */ if ((COV_Subscriptions[index].flag.valid) && (COV_Subscriptions[index].flag.issueConfirmedNotifications) && (COV_Subscriptions[index].invokeID)) { if (tsm_invoke_id_free(COV_Subscriptions[index].invokeID)) { COV_Subscriptions[index].invokeID = 0; } else if (tsm_invoke_id_failed(COV_Subscriptions [index].invokeID)) { tsm_free_invoke_id(COV_Subscriptions[index].invokeID); COV_Subscriptions[index].invokeID = 0; } } index++; if (index >= MAX_COV_SUBCRIPTIONS) { index = 0; cov_task_state = COV_STATE_SEND; } break; case COV_STATE_SEND: /* send any COVs that are requested */ if ((COV_Subscriptions[index].flag.valid) && (COV_Subscriptions[index].flag.send_requested)) { send = true; if (COV_Subscriptions[index].flag.issueConfirmedNotifications) { if (COV_Subscriptions[index].invokeID != 0) { /* already sending */ send = false; } if (!tsm_transaction_available()) { /* no transactions available - can't send now */ send = false; } } if (send) { object_type = (BACNET_OBJECT_TYPE) COV_Subscriptions[index]. monitoredObjectIdentifier.type; object_instance = COV_Subscriptions[index]. monitoredObjectIdentifier.instance; #if PRINT_ENABLED fprintf(stderr, "COVtask: Sending...\n"); #endif /* configure the linked list for the two properties */ value_list[0].next = &value_list[1]; value_list[1].next = NULL; (void) Device_Encode_Value_List(object_type, object_instance, &value_list[0]); status = cov_send_request(&COV_Subscriptions[index], &value_list[0]); if (status) { COV_Subscriptions[index].flag.send_requested = false; } } } index++; if (index >= MAX_COV_SUBCRIPTIONS) { index = 0; cov_task_state = COV_STATE_IDLE; } break; default: index = 0; cov_task_state = COV_STATE_IDLE; break; } }