1+ #include <ctype.h>
2+ #include <jansson.h>
3+ #include <stdlib.h>
4+ #include <string.h>
5+
6+ #include "handle.h"
7+ #include "modbus_tcp_simulator.h"
8+ #include "utils/http.h"
9+ #include "utils/log.h"
10+ #include "json/neu_json_fn.h"
11+
12+ static int extract_hold_start_from_addr (const char * addr_str ,
13+ uint16_t * out_idx0 )
14+ {
15+ if (!addr_str || !out_idx0 )
16+ return -1 ;
17+ const char * p = strstr (addr_str , "!4" );
18+ if (!p )
19+ return -1 ;
20+ p += 2 ;
21+ if (!isdigit ((unsigned char ) * p ))
22+ return -1 ;
23+ long v = strtol (p , NULL , 10 );
24+ if (v <= 0 || v > 65535 )
25+ return -1 ;
26+ * out_idx0 = (uint16_t )(v - 1 );
27+ return 0 ;
28+ }
29+
30+ void handle_simulator_status (nng_aio * aio )
31+ {
32+ NEU_VALIDATE_JWT (aio );
33+ neu_modbus_simulator_status_t st = { 0 };
34+ neu_modbus_simulator_get_status (& st );
35+ char buf [256 ] = { 0 };
36+ snprintf (buf , sizeof (buf ),
37+ "{\"running\":%d,\"port\":%u,\"tag_count\":%d,\"error\":%d}" ,
38+ st .running ? 1 : 0 , st .port , st .tag_count , st .error );
39+ neu_http_ok (aio , buf );
40+ }
41+
42+ void handle_simulator_start (nng_aio * aio )
43+ {
44+ NEU_VALIDATE_JWT (aio );
45+ int rc = neu_modbus_simulator_start (NULL , 0 );
46+
47+ neu_modbus_simulator_status_t st = { 0 };
48+ neu_modbus_simulator_get_status (& st );
49+ if (rc != 0 || (!st .running && st .error != 0 )) {
50+ char buf [64 ] = { 0 };
51+ snprintf (buf , sizeof (buf ), "{\"error\":%d}" , st .error );
52+ neu_http_ok (aio , buf );
53+ return ;
54+ }
55+ neu_http_ok (aio , "{\"error\":0}" );
56+ }
57+
58+ void handle_simulator_list_tags (nng_aio * aio )
59+ {
60+ NEU_VALIDATE_JWT (aio );
61+ char * out = neu_modbus_simulator_list_tags_json ();
62+ if (!out ) {
63+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_EINTERNAL , {
64+ neu_http_response (aio , NEU_ERR_EINTERNAL , result_error );
65+ });
66+ return ;
67+ }
68+ neu_http_ok (aio , out );
69+ free (out );
70+ }
71+
72+ void handle_simulator_stop (nng_aio * aio )
73+ {
74+ NEU_VALIDATE_JWT (aio );
75+ neu_modbus_simulator_stop ();
76+ neu_http_ok (aio , "{\"error\":0}" );
77+ }
78+
79+ void handle_simulator_set_config (nng_aio * aio )
80+ {
81+ NEU_VALIDATE_JWT (aio );
82+ char * body = NULL ;
83+ size_t sz = 0 ;
84+ if (neu_http_get_body (aio , (void * * ) & body , & sz ) != 0 || !body ) {
85+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_PARAM_IS_WRONG , {
86+ neu_http_response (aio , NEU_ERR_PARAM_IS_WRONG , result_error );
87+ });
88+ return ;
89+ }
90+
91+ json_error_t jerr ;
92+ json_t * root = json_loads (body , 0 , & jerr );
93+ free (body );
94+ if (!root ) {
95+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_PARAM_IS_WRONG , {
96+ neu_http_response (aio , NEU_ERR_PARAM_IS_WRONG , result_error );
97+ });
98+ return ;
99+ }
100+ json_t * tags = json_object_get (root , "tags" );
101+ if (!tags || !json_is_array (tags )) {
102+ json_decref (root );
103+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_PARAM_IS_WRONG , {
104+ neu_http_response (aio , NEU_ERR_PARAM_IS_WRONG , result_error );
105+ });
106+ return ;
107+ }
108+
109+ int count = 0 ;
110+ for (size_t i = 0 ; i < json_array_size (tags ); ++ i ) {
111+ json_t * obj = json_array_get (tags , i );
112+ if (!obj || !json_is_object (obj ))
113+ continue ;
114+ json_t * jaddr = json_object_get (obj , "address" );
115+ json_t * jtype = json_object_get (obj , "type" );
116+ if (!jaddr || !json_is_string (jaddr ) || !jtype )
117+ continue ;
118+ const char * addr_str = json_string_value (jaddr );
119+ uint16_t idx0 = 0 ;
120+ if (extract_hold_start_from_addr (addr_str , & idx0 ) != 0 )
121+ continue ;
122+ count ++ ;
123+ }
124+
125+ char * * names = NULL ;
126+ char * * addresses = NULL ;
127+ uint16_t * indices = NULL ;
128+ neu_sim_tag_type_e * types = NULL ;
129+ if (count > 0 ) {
130+ names = calloc ((size_t ) count , sizeof (char * ));
131+ addresses = calloc ((size_t ) count , sizeof (char * ));
132+ indices = calloc ((size_t ) count , sizeof (uint16_t ));
133+ types = calloc ((size_t ) count , sizeof (neu_sim_tag_type_e ));
134+ if (!names || !addresses || !indices || !types ) {
135+ free (names );
136+ free (addresses );
137+ free (indices );
138+ free (types );
139+ json_decref (root );
140+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_EINTERNAL , {
141+ neu_http_response (aio , NEU_ERR_EINTERNAL , result_error );
142+ });
143+ return ;
144+ }
145+ }
146+
147+ int m = 0 ;
148+ for (size_t i = 0 ; i < json_array_size (tags ); ++ i ) {
149+ json_t * obj = json_array_get (tags , i );
150+ if (!obj || !json_is_object (obj ))
151+ continue ;
152+ json_t * jname = json_object_get (obj , "name" );
153+ json_t * jaddr = json_object_get (obj , "address" );
154+ json_t * jtype = json_object_get (obj , "type" );
155+ if (!jaddr || !json_is_string (jaddr ) || !jtype )
156+ continue ;
157+ const char * addr_str = json_string_value (jaddr );
158+ uint16_t idx0 = 0 ;
159+ if (extract_hold_start_from_addr (addr_str , & idx0 ) != 0 )
160+ continue ;
161+ neu_sim_tag_type_e tp = NEU_SIM_TAG_NONE ;
162+ if (json_is_string (jtype )) {
163+ const char * ts = json_string_value (jtype );
164+ if (ts ) {
165+ if (strcmp (ts , "sine" ) == 0 )
166+ tp = NEU_SIM_TAG_SINE ;
167+ else if (strcmp (ts , "saw" ) == 0 )
168+ tp = NEU_SIM_TAG_SAW ;
169+ else if (strcmp (ts , "square" ) == 0 )
170+ tp = NEU_SIM_TAG_SQUARE ;
171+ else if (strcmp (ts , "random" ) == 0 )
172+ tp = NEU_SIM_TAG_RANDOM ;
173+ }
174+ } else if (json_is_integer (jtype )) {
175+ tp = (neu_sim_tag_type_e ) json_integer_value (jtype );
176+ }
177+ if (tp == NEU_SIM_TAG_NONE || idx0 >= 1000 )
178+ continue ;
179+ indices [m ] = idx0 ;
180+ types [m ] = tp ;
181+ names [m ] = jname && json_is_string (jname )
182+ ? strdup (json_string_value (jname ))
183+ : strdup ("" );
184+ addresses [m ] = strdup (addr_str );
185+ m ++ ;
186+ }
187+ json_decref (root );
188+
189+ neu_modbus_simulator_config_tags (
190+ (const char * * ) names , (const char * * ) addresses , indices , types , m );
191+
192+ for (int i = 0 ; i < m ; ++ i ) {
193+ free (names [i ]);
194+ free (addresses [i ]);
195+ }
196+ free (names );
197+ free (addresses );
198+ free (indices );
199+ free (types );
200+ neu_http_ok (aio , "{\"error\":0}" );
201+ }
202+
203+ void handle_simulator_export (nng_aio * aio )
204+ {
205+ NEU_VALIDATE_JWT (aio );
206+ char * drivers = neu_modbus_simulator_export_drivers_json ();
207+ if (!drivers ) {
208+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_EINTERNAL , {
209+ neu_http_response (aio , NEU_ERR_EINTERNAL , result_error );
210+ });
211+ return ;
212+ }
213+ neu_http_response_file (
214+ aio , drivers , strlen (drivers ),
215+ "attachment; filename=\"simulator_modbus_south.json\"" );
216+ free (drivers );
217+ }
0 commit comments