|  |  | @ -36,7 +36,7 @@ static TF_Result unit_report_lst(TinyFrame *tf, TF_Msg *msg) | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint8_t callsign = msg->data[0]; |  |  |  |     uint8_t callsign = msg->data[0]; | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint8_t rpt_type = msg->data[1]; |  |  |  |     uint8_t rpt_type = msg->data[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     struct gex_unit_lu *lu = find_unit_by_callsign(gex, callsign); |  |  |  |     struct gex_unit_lu *lu = gex_find_unit_by_callsign(gex, callsign); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if (lu && lu->report_handler) { |  |  |  |     if (lu && lu->report_handler) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         lu->report_handler(gex, lu->name, rpt_type, |  |  |  |         lu->report_handler(gex, lu->name, rpt_type, | 
			
		
	
		
		
			
				
					
					|  |  |  |                            msg->data+2, (uint32_t) (msg->len - 2)); |  |  |  |                            msg->data+2, (uint32_t) (msg->len - 2)); | 
			
		
	
	
		
		
			
				
					|  |  | @ -54,7 +54,7 @@ static TF_Result list_units_lst(TinyFrame *tf, TF_Msg *msg) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GexClient *gex = tf->userdata; |  |  |  |     GexClient *gex = tf->userdata; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     destroy_unit_lookup(gex); |  |  |  |     gex_destroy_unit_lookup(gex); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     PayloadParser pp = pp_start((uint8_t*)msg->data, msg->len, NULL); |  |  |  |     PayloadParser pp = pp_start((uint8_t*)msg->data, msg->len, NULL); | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint8_t count = pp_u8(&pp); |  |  |  |     uint8_t count = pp_u8(&pp); | 
			
		
	
	
		
		
			
				
					|  |  | @ -63,7 +63,7 @@ static TF_Result list_units_lst(TinyFrame *tf, TF_Msg *msg) | 
			
		
	
		
		
			
				
					
					|  |  |  |     for(int i = 0; i < count; i++) { |  |  |  |     for(int i = 0; i < count; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         uint8_t callsign = pp_u8(&pp); |  |  |  |         uint8_t callsign = pp_u8(&pp); | 
			
		
	
		
		
			
				
					
					|  |  |  |         pp_string(&pp, buf, 100); |  |  |  |         pp_string(&pp, buf, 100); | 
			
		
	
		
		
			
				
					
					|  |  |  |         fprintf(stderr, "Available unit \"%s\" @ %d\n", buf, callsign); |  |  |  |         fprintf(stderr, "- Found unit \"%s\" @ callsign %d\n", buf, callsign); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // append
 |  |  |  |         // append
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         struct gex_unit_lu *lu = malloc(sizeof(struct gex_unit_lu)); |  |  |  |         struct gex_unit_lu *lu = malloc(sizeof(struct gex_unit_lu)); | 
			
		
	
	
		
		
			
				
					|  |  | @ -90,9 +90,9 @@ void GEX_OnReport(GexClient *gex, const char *unit_name, GEX_ReportListener lst) | 
			
		
	
		
		
			
				
					
					|  |  |  |         gex->fallback_report_handler = lst; |  |  |  |         gex->fallback_report_handler = lst; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     else { |  |  |  |     else { | 
			
		
	
		
		
			
				
					
					|  |  |  |         struct gex_unit_lu *lu = find_unit_by_name(gex, unit_name); |  |  |  |         struct gex_unit_lu *lu = gex_find_unit_by_name(gex, unit_name); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         if (!lu) { |  |  |  |         if (!lu) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             fprintf(stderr, "No unit named \"%s\"!", unit_name); |  |  |  |             fprintf(stderr, "No unit named \"%s\", can't bind listener!", unit_name); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         else { |  |  |  |         else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             lu->report_handler = lst; |  |  |  |             lu->report_handler = lst; | 
			
		
	
	
		
		
			
				
					|  |  | @ -121,6 +121,7 @@ GexClient *GEX_Init(const char *device, int timeout_ms) | 
			
		
	
		
		
			
				
					
					|  |  |  |     gex->tf->userdata = gex; |  |  |  |     gex->tf->userdata = gex; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // --- Test connectivity ---
 |  |  |  |     // --- Test connectivity ---
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "Testing connection...\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |     TF_QuerySimple(gex->tf, MSG_PING, /*pld*/ NULL, 0, /*cb*/ connectivity_check_lst, 0); |  |  |  |     TF_QuerySimple(gex->tf, MSG_PING, /*pld*/ NULL, 0, /*cb*/ connectivity_check_lst, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     GEX_Poll(gex); |  |  |  |     GEX_Poll(gex); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -131,9 +132,11 @@ GexClient *GEX_Init(const char *device, int timeout_ms) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // --- populate callsign look-up table ---
 |  |  |  |     // --- populate callsign look-up table ---
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "Loading available units info...\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |     TF_QuerySimple(gex->tf, MSG_LIST_UNITS, /*pld*/ NULL, 0, /*cb*/ list_units_lst, 0); |  |  |  |     TF_QuerySimple(gex->tf, MSG_LIST_UNITS, /*pld*/ NULL, 0, /*cb*/ list_units_lst, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     GEX_Poll(gex); |  |  |  |     GEX_Poll(gex); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // Bind the catch-all event handler. Will be re-distributed to individual unit listeners if needed.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     TF_AddTypeListener(gex->tf, MSG_UNIT_REPORT, unit_report_lst); |  |  |  |     TF_AddTypeListener(gex->tf, MSG_UNIT_REPORT, unit_report_lst); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     return gex; |  |  |  |     return gex; | 
			
		
	
	
		
		
			
				
					|  |  | @ -162,7 +165,7 @@ void GEX_DeInit(GexClient *gex) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (gex == NULL) return; |  |  |  |     if (gex == NULL) return; | 
			
		
	
		
		
			
				
					
					|  |  |  |     close(gex->acm_fd); |  |  |  |     close(gex->acm_fd); | 
			
		
	
		
		
			
				
					
					|  |  |  |     destroy_unit_lookup(gex); |  |  |  |     gex_destroy_unit_lookup(gex); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     TF_DeInit(gex->tf); |  |  |  |     TF_DeInit(gex->tf); | 
			
		
	
		
		
			
				
					
					|  |  |  |     free(gex); |  |  |  |     free(gex); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | @ -174,16 +177,16 @@ void GEX_Query(GexClient *gex, | 
			
		
	
		
		
			
				
					
					|  |  |  |                uint8_t *payload, uint32_t len, |  |  |  |                uint8_t *payload, uint32_t len, | 
			
		
	
		
		
			
				
					
					|  |  |  |                TF_Listener listener) |  |  |  |                TF_Listener listener) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint8_t callsign = find_callsign_by_name(gex, unit); |  |  |  |     uint8_t callsign = gex_find_callsign_by_name(gex, unit); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     assert(callsign != 0); |  |  |  |     assert(callsign != 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint8_t *pld = malloc(len + 2); |  |  |  |     uint8_t *pld = malloc(len + 2); | 
			
		
	
		
		
			
				
					
					|  |  |  |     assert(pld != NULL); |  |  |  |     assert(pld != NULL); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |     { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         // prefix the actual payload with the callsign and command bytes.
 |  |  |  |         // prefix the actual payload with the callsign and command bytes.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // TODO provide TF API for sending the payload externally in smaller chunks? Will avoid the malloc here
 |  |  |  |         // TODO provide TF API for sending the payload externally in smaller chunks? Will avoid the malloc here
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         pld[0] = callsign; |  |  |  |         pld[0] = callsign; | 
			
		
	
		
		
			
				
					
					|  |  |  |         pld[1] = cmd; |  |  |  |         pld[1] = cmd; | 
			
		
	
		
		
			
				
					
					|  |  |  |     memcpy(pld+2, payload, len); |  |  |  |         memcpy(pld + 2, payload, len); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         TF_Msg msg; |  |  |  |         TF_Msg msg; | 
			
		
	
		
		
			
				
					
					|  |  |  |         TF_ClearMsg(&msg); |  |  |  |         TF_ClearMsg(&msg); | 
			
		
	
	
		
		
			
				
					|  |  | @ -191,6 +194,7 @@ void GEX_Query(GexClient *gex, | 
			
		
	
		
		
			
				
					
					|  |  |  |         msg.data = pld; |  |  |  |         msg.data = pld; | 
			
		
	
		
		
			
				
					
					|  |  |  |         msg.len = (TF_LEN) (len + 2); |  |  |  |         msg.len = (TF_LEN) (len + 2); | 
			
		
	
		
		
			
				
					
					|  |  |  |         TF_Query(gex->tf, &msg, listener, 0); |  |  |  |         TF_Query(gex->tf, &msg, listener, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     free(pld); |  |  |  |     free(pld); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (NULL != listener) { |  |  |  |     if (NULL != listener) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -224,7 +228,6 @@ TF_Msg *GEX_SyncQuery(GexClient *gex, | 
			
		
	
		
		
			
				
					
					|  |  |  |     return gex->sync_query_ok ? &gex->sync_query_response : NULL; |  |  |  |     return gex->sync_query_ok ? &gex->sync_query_response : NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | /** Command a unit (same like query, but without listener and without polling) */ |  |  |  | /** Command a unit (same like query, but without listener and without polling) */ | 
			
		
	
		
		
			
				
					
					|  |  |  | void GEX_Send(GexClient *gex, |  |  |  | void GEX_Send(GexClient *gex, | 
			
		
	
		
		
			
				
					
					|  |  |  |               const char *unit, uint8_t cmd, |  |  |  |               const char *unit, uint8_t cmd, | 
			
		
	
	
		
		
			
				
					|  |  | 
 |