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 , strdup (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 , strdup (buf ));
53+ return ;
54+ }
55+ neu_http_ok (aio , strdup ("{\"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+ }
70+
71+ void handle_simulator_stop (nng_aio * aio )
72+ {
73+ NEU_VALIDATE_JWT (aio );
74+ neu_modbus_simulator_stop ();
75+ neu_http_ok (aio , strdup ("{\"error\":0}" ));
76+ }
77+
78+ void handle_simulator_set_config (nng_aio * aio )
79+ {
80+ NEU_VALIDATE_JWT (aio );
81+ char * body = NULL ;
82+ size_t sz = 0 ;
83+ if (neu_http_get_body (aio , (void * * ) & body , & sz ) != 0 || !body ) {
84+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_PARAM_IS_WRONG , {
85+ neu_http_response (aio , NEU_ERR_PARAM_IS_WRONG , result_error );
86+ });
87+ return ;
88+ }
89+
90+ json_error_t jerr ;
91+ json_t * root = json_loads (body , 0 , & jerr );
92+ free (body );
93+ if (!root ) {
94+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_PARAM_IS_WRONG , {
95+ neu_http_response (aio , NEU_ERR_PARAM_IS_WRONG , result_error );
96+ });
97+ return ;
98+ }
99+ json_t * tags = json_object_get (root , "tags" );
100+ if (!tags || !json_is_array (tags )) {
101+ json_decref (root );
102+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_PARAM_IS_WRONG , {
103+ neu_http_response (aio , NEU_ERR_PARAM_IS_WRONG , result_error );
104+ });
105+ return ;
106+ }
107+
108+ int count = 0 ;
109+ for (size_t i = 0 ; i < json_array_size (tags ); ++ i ) {
110+ json_t * obj = json_array_get (tags , i );
111+ if (!obj || !json_is_object (obj ))
112+ continue ;
113+ json_t * jaddr = json_object_get (obj , "address" );
114+ json_t * jtype = json_object_get (obj , "type" );
115+ if (!jaddr || !json_is_string (jaddr ) || !jtype )
116+ continue ;
117+ const char * addr_str = json_string_value (jaddr );
118+ uint16_t idx0 = 0 ;
119+ if (extract_hold_start_from_addr (addr_str , & idx0 ) != 0 )
120+ continue ;
121+ count ++ ;
122+ }
123+
124+ char * * names = NULL ;
125+ char * * addresses = NULL ;
126+ uint16_t * indices = NULL ;
127+ neu_sim_tag_type_e * types = NULL ;
128+ if (count > 0 ) {
129+ names = calloc ((size_t ) count , sizeof (char * ));
130+ addresses = calloc ((size_t ) count , sizeof (char * ));
131+ indices = calloc ((size_t ) count , sizeof (uint16_t ));
132+ types = calloc ((size_t ) count , sizeof (neu_sim_tag_type_e ));
133+ if (!names || !addresses || !indices || !types ) {
134+ free (names );
135+ free (addresses );
136+ free (indices );
137+ free (types );
138+ json_decref (root );
139+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_EINTERNAL , {
140+ neu_http_response (aio , NEU_ERR_EINTERNAL , result_error );
141+ });
142+ return ;
143+ }
144+ }
145+
146+ int m = 0 ;
147+ for (size_t i = 0 ; i < json_array_size (tags ); ++ i ) {
148+ json_t * obj = json_array_get (tags , i );
149+ if (!obj || !json_is_object (obj ))
150+ continue ;
151+ json_t * jname = json_object_get (obj , "name" );
152+ json_t * jaddr = json_object_get (obj , "address" );
153+ json_t * jtype = json_object_get (obj , "type" );
154+ if (!jaddr || !json_is_string (jaddr ) || !jtype )
155+ continue ;
156+ const char * addr_str = json_string_value (jaddr );
157+ uint16_t idx0 = 0 ;
158+ if (extract_hold_start_from_addr (addr_str , & idx0 ) != 0 )
159+ continue ;
160+ neu_sim_tag_type_e tp = NEU_SIM_TAG_NONE ;
161+ if (json_is_string (jtype )) {
162+ const char * ts = json_string_value (jtype );
163+ if (ts ) {
164+ if (strcmp (ts , "sine" ) == 0 )
165+ tp = NEU_SIM_TAG_SINE ;
166+ else if (strcmp (ts , "saw" ) == 0 )
167+ tp = NEU_SIM_TAG_SAW ;
168+ else if (strcmp (ts , "square" ) == 0 )
169+ tp = NEU_SIM_TAG_SQUARE ;
170+ else if (strcmp (ts , "random" ) == 0 )
171+ tp = NEU_SIM_TAG_RANDOM ;
172+ }
173+ } else if (json_is_integer (jtype )) {
174+ tp = (neu_sim_tag_type_e ) json_integer_value (jtype );
175+ }
176+ if (tp == NEU_SIM_TAG_NONE || idx0 >= 1000 )
177+ continue ;
178+ indices [m ] = idx0 ;
179+ types [m ] = tp ;
180+ names [m ] = jname && json_is_string (jname )
181+ ? strdup (json_string_value (jname ))
182+ : strdup ("" );
183+ addresses [m ] = strdup (addr_str );
184+ m ++ ;
185+ }
186+ json_decref (root );
187+
188+ neu_modbus_simulator_config_tags (
189+ (const char * * ) names , (const char * * ) addresses , indices , types , m );
190+
191+ for (int i = 0 ; i < m ; ++ i ) {
192+ free (names [i ]);
193+ free (addresses [i ]);
194+ }
195+ free (names );
196+ free (addresses );
197+ free (indices );
198+ free (types );
199+ neu_http_ok (aio , strdup ("{\"error\":0}" ));
200+ }
201+
202+ void handle_simulator_export (nng_aio * aio )
203+ {
204+ NEU_VALIDATE_JWT (aio );
205+ char * drivers = neu_modbus_simulator_export_drivers_json ();
206+ if (!drivers ) {
207+ NEU_JSON_RESPONSE_ERROR (NEU_ERR_EINTERNAL , {
208+ neu_http_response (aio , NEU_ERR_EINTERNAL , result_error );
209+ });
210+ return ;
211+ }
212+ neu_http_response_file (
213+ aio , drivers , strlen (drivers ),
214+ "attachment; filename=\"simulator_modbus_south.json\"" );
215+ free (drivers );
216+ }
0 commit comments