@@ -50,7 +50,7 @@ describe('Modbus Protocol Helpers', () => {
5050 // Response: unit=1, func=3, byteCount=2, value=230
5151 const response = Buffer . from ( [ 0x01 , 0x03 , 0x02 , 0x00 , 0xe6 ] )
5252
53- const values = parseRegisterReadResponse ( response )
53+ const values = parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } )
5454
5555 expect ( values ) . toEqual ( [ 230 ] )
5656 } )
@@ -59,21 +59,79 @@ describe('Modbus Protocol Helpers', () => {
5959 // Response: unit=1, func=3, byteCount=4, values=[230, 52]
6060 const response = Buffer . from ( [ 0x01 , 0x03 , 0x04 , 0x00 , 0xe6 , 0x00 , 0x34 ] )
6161
62- const values = parseRegisterReadResponse ( response )
62+ const values = parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } )
6363
6464 expect ( values ) . toEqual ( [ 230 , 52 ] )
6565 } )
6666
6767 it ( 'should throw error on invalid response length' , ( ) => {
6868 const response = Buffer . from ( [ 0x01 , 0x03 , 0x02 ] ) // Missing data
6969
70- expect ( ( ) => parseRegisterReadResponse ( response ) ) . toThrow ( 'Invalid response' )
70+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
71+ 'Invalid response'
72+ )
7173 } )
7274
7375 it ( 'should throw error on undefined byte count' , ( ) => {
7476 const response = Buffer . from ( [ 0x01 , 0x03 ] ) // Missing byte count
7577
76- expect ( ( ) => parseRegisterReadResponse ( response ) ) . toThrow ( 'Invalid response' )
78+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
79+ 'Invalid response'
80+ )
81+ } )
82+
83+ it ( 'should throw error when unitID does not match' , ( ) => {
84+ const response = Buffer . from ( [ 0x02 , 0x03 , 0x02 , 0x00 , 0xe6 ] )
85+
86+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
87+ 'Response unitID mismatch: expected 1, got 2'
88+ )
89+ } )
90+
91+ it ( 'should throw error when functionCode does not match (non-exception)' , ( ) => {
92+ const response = Buffer . from ( [ 0x01 , 0x04 , 0x02 , 0x00 , 0xe6 ] )
93+
94+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
95+ 'Response function code mismatch: expected 3, got 4'
96+ )
97+ } )
98+
99+ it ( 'should throw error on Modbus exception response' , ( ) => {
100+ // Exception response: unit=1, func=0x83 (0x03 + 0x80), exceptionCode=2
101+ const response = Buffer . from ( [ 0x01 , 0x83 , 0x02 ] )
102+
103+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
104+ 'Modbus exception response: function code 3, exception code 2'
105+ )
106+ } )
107+
108+ it ( 'should throw error when byte count is odd' , ( ) => {
109+ const response = Buffer . from ( [ 0x01 , 0x03 , 0x03 , 0x00 , 0xe6 , 0x00 ] )
110+
111+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
112+ 'Invalid byte count: 3 (must be even for 16-bit registers)'
113+ )
114+ } )
115+
116+ it ( 'should throw error when byte count exceeds maximum' , ( ) => {
117+ const byteCount = 252 // Exceeds max of 250
118+ const response = Buffer . alloc ( 3 + byteCount )
119+ response [ 0 ] = 0x01
120+ response [ 1 ] = 0x03
121+ response [ 2 ] = byteCount
122+
123+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
124+ 'Invalid byte count: 252 (maximum is 250)'
125+ )
126+ } )
127+
128+ it ( 'should throw error when byte count does not match buffer length' , ( ) => {
129+ // Declares 6 bytes but only provides 4
130+ const response = Buffer . from ( [ 0x01 , 0x03 , 0x06 , 0x00 , 0xe6 , 0x00 , 0x34 ] )
131+
132+ expect ( ( ) => parseRegisterReadResponse ( response , { unitID : 1 , functionCode : 0x03 } ) ) . toThrow (
133+ 'Invalid response: buffer length 7 does not match expected length 9 (3 + byteCount 6)'
134+ )
77135 } )
78136 } )
79137
@@ -159,7 +217,7 @@ describe('Modbus Protocol Helpers', () => {
159217 // Response: unit=1, func=1, byteCount=1, coilByte=0x01 (bit 0 = 1)
160218 const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 , 0x01 ] )
161219
162- const value = parseCoilReadResponse ( response )
220+ const value = parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } )
163221
164222 expect ( value ) . toBe ( true )
165223 } )
@@ -168,7 +226,7 @@ describe('Modbus Protocol Helpers', () => {
168226 // Response: unit=1, func=1, byteCount=1, coilByte=0x00 (bit 0 = 0)
169227 const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 , 0x00 ] )
170228
171- const value = parseCoilReadResponse ( response )
229+ const value = parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } )
172230
173231 expect ( value ) . toBe ( false )
174232 } )
@@ -177,7 +235,7 @@ describe('Modbus Protocol Helpers', () => {
177235 // Response: coilByte=0xFF (bit 0 = 1)
178236 const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 , 0xff ] )
179237
180- const value = parseCoilReadResponse ( response )
238+ const value = parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } )
181239
182240 expect ( value ) . toBe ( true )
183241 } )
@@ -186,27 +244,88 @@ describe('Modbus Protocol Helpers', () => {
186244 // Response: coilByte=0xFE (bit 0 = 0, other bits = 1)
187245 const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 , 0xfe ] )
188246
189- const value = parseCoilReadResponse ( response )
247+ const value = parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } )
190248
191249 expect ( value ) . toBe ( false )
192250 } )
193251
194252 it ( 'should throw error on invalid response length' , ( ) => {
195253 const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 ] ) // Missing coil byte
196254
197- expect ( ( ) => parseCoilReadResponse ( response ) ) . toThrow ( 'Invalid response' )
255+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
256+ 'Invalid response'
257+ )
198258 } )
199259
200260 it ( 'should throw error on undefined byte count' , ( ) => {
201261 const response = Buffer . from ( [ 0x01 , 0x01 ] ) // Missing byte count
202262
203- expect ( ( ) => parseCoilReadResponse ( response ) ) . toThrow ( 'Invalid response' )
263+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
264+ 'Invalid response'
265+ )
204266 } )
205267
206268 it ( 'should throw error on undefined coil byte' , ( ) => {
207269 const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 ] ) // byte count present but no data
208270
209- expect ( ( ) => parseCoilReadResponse ( response ) ) . toThrow ( 'Invalid response' )
271+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
272+ 'Invalid response'
273+ )
274+ } )
275+
276+ it ( 'should throw error when unitID does not match' , ( ) => {
277+ const response = Buffer . from ( [ 0x02 , 0x01 , 0x01 , 0x01 ] )
278+
279+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
280+ 'Response unitID mismatch: expected 1, got 2'
281+ )
282+ } )
283+
284+ it ( 'should throw error when functionCode does not match (non-exception)' , ( ) => {
285+ const response = Buffer . from ( [ 0x01 , 0x02 , 0x01 , 0x01 ] )
286+
287+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
288+ 'Response function code mismatch: expected 1, got 2'
289+ )
290+ } )
291+
292+ it ( 'should throw error on Modbus exception response' , ( ) => {
293+ // Exception response: unit=1, func=0x81 (0x01 + 0x80), exceptionCode=3
294+ const response = Buffer . from ( [ 0x01 , 0x81 , 0x03 ] )
295+
296+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
297+ 'Modbus exception response: function code 1, exception code 3'
298+ )
299+ } )
300+
301+ it ( 'should throw error when byte count exceeds maximum' , ( ) => {
302+ const byteCount = 252 // Exceeds max of 250
303+ const response = Buffer . alloc ( 3 + byteCount )
304+ response [ 0 ] = 0x01
305+ response [ 1 ] = 0x01
306+ response [ 2 ] = byteCount
307+
308+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
309+ 'Invalid byte count: 252 (maximum is 250)'
310+ )
311+ } )
312+
313+ it ( 'should throw error when byte count does not match buffer length' , ( ) => {
314+ // Declares 2 bytes but only provides 1
315+ const response = Buffer . from ( [ 0x01 , 0x01 , 0x02 , 0x01 ] )
316+
317+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
318+ 'Invalid response: buffer length 4 does not match expected length 5 (3 + byteCount 2)'
319+ )
320+ } )
321+
322+ it ( 'should throw error when buffer has extra bytes' , ( ) => {
323+ // Declares 1 byte but provides 4 extra bytes
324+ const response = Buffer . from ( [ 0x01 , 0x01 , 0x01 , 0x01 , 0xff , 0xff , 0xff , 0xff ] )
325+
326+ expect ( ( ) => parseCoilReadResponse ( response , { unitID : 1 , functionCode : 0x01 } ) ) . toThrow (
327+ 'Invalid response: buffer length 8 does not match expected length 4 (3 + byteCount 1)'
328+ )
210329 } )
211330 } )
212331
0 commit comments