or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client.mddatastore.mdindex.mdpdu.mdserver.md

pdu.mddocs/

0

# PDU Messages

1

2

PyModbus provides complete implementation of all standard Modbus Protocol Data Units (PDUs) including bit operations, register operations, file operations, diagnostic functions, and device information queries. PDU classes can be used directly for custom protocol implementations or advanced use cases.

3

4

## Capabilities

5

6

### Base PDU Classes

7

8

Core PDU classes providing the foundation for all Modbus messages.

9

10

```python { .api }

11

class ModbusPDU:

12

def __init__(self, **kwargs): ...

13

def encode(self) -> bytes: ...

14

def decode(self, data: bytes): ...

15

def calculate_rtu_frame_size(data: bytes) -> int: ...

16

17

class ExceptionResponse(ModbusPDU):

18

function_code = 0x80

19

def __init__(self, function_code, exception_code=None, **kwargs): ...

20

def encode(self) -> bytes: ...

21

def decode(self, data: bytes): ...

22

23

class DecodePDU:

24

def __init__(self, data: bytes, **kwargs): ...

25

def decode(self) -> ModbusPDU: ...

26

```

27

28

### Bit Access Operations

29

30

PDU messages for reading and writing coil (binary) values.

31

32

```python { .api }

33

# Read Coils (FC 01)

34

class ReadCoilsRequest(ModbusPDU):

35

function_code = 0x01

36

def __init__(self, address=None, count=None, slave=0, **kwargs): ...

37

def encode(self) -> bytes: ...

38

def decode(self, data: bytes): ...

39

40

class ReadCoilsResponse(ModbusPDU):

41

function_code = 0x01

42

def __init__(self, values=None, **kwargs): ...

43

@property

44

def bits(self) -> list: ...

45

def encode(self) -> bytes: ...

46

def decode(self, data: bytes): ...

47

48

# Read Discrete Inputs (FC 02)

49

class ReadDiscreteInputsRequest(ModbusPDU):

50

function_code = 0x02

51

def __init__(self, address=None, count=None, slave=0, **kwargs): ...

52

def encode(self) -> bytes: ...

53

def decode(self, data: bytes): ...

54

55

class ReadDiscreteInputsResponse(ModbusPDU):

56

function_code = 0x02

57

def __init__(self, values=None, **kwargs): ...

58

@property

59

def bits(self) -> list: ...

60

def encode(self) -> bytes: ...

61

def decode(self, data: bytes): ...

62

63

# Write Single Coil (FC 05)

64

class WriteSingleCoilRequest(ModbusPDU):

65

function_code = 0x05

66

def __init__(self, address=None, value=None, slave=0, **kwargs): ...

67

def encode(self) -> bytes: ...

68

def decode(self, data: bytes): ...

69

70

class WriteSingleCoilResponse(ModbusPDU):

71

function_code = 0x05

72

def __init__(self, address=None, value=None, **kwargs): ...

73

def encode(self) -> bytes: ...

74

def decode(self, data: bytes): ...

75

76

# Write Multiple Coils (FC 15)

77

class WriteMultipleCoilsRequest(ModbusPDU):

78

function_code = 0x0F

79

def __init__(self, address=None, values=None, slave=0, **kwargs): ...

80

def encode(self) -> bytes: ...

81

def decode(self, data: bytes): ...

82

83

class WriteMultipleCoilsResponse(ModbusPDU):

84

function_code = 0x0F

85

def __init__(self, address=None, count=None, **kwargs): ...

86

def encode(self) -> bytes: ...

87

def decode(self, data: bytes): ...

88

```

89

90

### Register Access Operations

91

92

PDU messages for reading and writing register (16-bit integer) values.

93

94

```python { .api }

95

# Read Holding Registers (FC 03)

96

class ReadHoldingRegistersRequest(ModbusPDU):

97

function_code = 0x03

98

def __init__(self, address=None, count=None, slave=0, **kwargs): ...

99

def encode(self) -> bytes: ...

100

def decode(self, data: bytes): ...

101

102

class ReadHoldingRegistersResponse(ModbusPDU):

103

function_code = 0x03

104

def __init__(self, values=None, **kwargs): ...

105

@property

106

def registers(self) -> list: ...

107

def encode(self) -> bytes: ...

108

def decode(self, data: bytes): ...

109

110

# Read Input Registers (FC 04)

111

class ReadInputRegistersRequest(ModbusPDU):

112

function_code = 0x04

113

def __init__(self, address=None, count=None, slave=0, **kwargs): ...

114

def encode(self) -> bytes: ...

115

def decode(self, data: bytes): ...

116

117

class ReadInputRegistersResponse(ModbusPDU):

118

function_code = 0x04

119

def __init__(self, values=None, **kwargs): ...

120

@property

121

def registers(self) -> list: ...

122

def encode(self) -> bytes: ...

123

def decode(self, data: bytes): ...

124

125

# Write Single Register (FC 06)

126

class WriteSingleRegisterRequest(ModbusPDU):

127

function_code = 0x06

128

def __init__(self, address=None, value=None, slave=0, **kwargs): ...

129

def encode(self) -> bytes: ...

130

def decode(self, data: bytes): ...

131

132

class WriteSingleRegisterResponse(ModbusPDU):

133

function_code = 0x06

134

def __init__(self, address=None, value=None, **kwargs): ...

135

def encode(self) -> bytes: ...

136

def decode(self, data: bytes): ...

137

138

# Write Multiple Registers (FC 16)

139

class WriteMultipleRegistersRequest(ModbusPDU):

140

function_code = 0x10

141

def __init__(self, address=None, values=None, slave=0, **kwargs): ...

142

def encode(self) -> bytes: ...

143

def decode(self, data: bytes): ...

144

145

class WriteMultipleRegistersResponse(ModbusPDU):

146

function_code = 0x10

147

def __init__(self, address=None, count=None, **kwargs): ...

148

def encode(self) -> bytes: ...

149

def decode(self, data: bytes): ...

150

151

# Read/Write Multiple Registers (FC 23)

152

class ReadWriteMultipleRegistersRequest(ModbusPDU):

153

function_code = 0x17

154

def __init__(self, read_address=None, read_count=None, write_address=None,

155

write_registers=None, slave=0, **kwargs): ...

156

def encode(self) -> bytes: ...

157

def decode(self, data: bytes): ...

158

159

class ReadWriteMultipleRegistersResponse(ModbusPDU):

160

function_code = 0x17

161

def __init__(self, values=None, **kwargs): ...

162

@property

163

def registers(self) -> list: ...

164

def encode(self) -> bytes: ...

165

def decode(self, data: bytes): ...

166

167

# Mask Write Register (FC 22)

168

class MaskWriteRegisterRequest(ModbusPDU):

169

function_code = 0x16

170

def __init__(self, address=None, and_mask=0xFFFF, or_mask=0x0000, slave=0, **kwargs): ...

171

def encode(self) -> bytes: ...

172

def decode(self, data: bytes): ...

173

174

class MaskWriteRegisterResponse(ModbusPDU):

175

function_code = 0x16

176

def __init__(self, address=None, and_mask=0xFFFF, or_mask=0x0000, **kwargs): ...

177

def encode(self) -> bytes: ...

178

def decode(self, data: bytes): ...

179

```

180

181

### File Record Operations

182

183

PDU messages for file record access operations.

184

185

```python { .api }

186

# File Record data structure

187

class FileRecord:

188

def __init__(self, file_number=0x00, record_number=0x0000, record_data=None): ...

189

def encode(self) -> bytes: ...

190

def decode(self, data: bytes): ...

191

192

# Read File Record (FC 20)

193

class ReadFileRecordRequest(ModbusPDU):

194

function_code = 0x14

195

def __init__(self, records=None, slave=0, **kwargs): ...

196

def encode(self) -> bytes: ...

197

def decode(self, data: bytes): ...

198

199

class ReadFileRecordResponse(ModbusPDU):

200

function_code = 0x14

201

def __init__(self, records=None, **kwargs): ...

202

def encode(self) -> bytes: ...

203

def decode(self, data: bytes): ...

204

205

# Write File Record (FC 21)

206

class WriteFileRecordRequest(ModbusPDU):

207

function_code = 0x15

208

def __init__(self, records=None, slave=0, **kwargs): ...

209

def encode(self) -> bytes: ...

210

def decode(self, data: bytes): ...

211

212

class WriteFileRecordResponse(ModbusPDU):

213

function_code = 0x15

214

def __init__(self, records=None, **kwargs): ...

215

def encode(self) -> bytes: ...

216

def decode(self, data: bytes): ...

217

218

# Read FIFO Queue (FC 24)

219

class ReadFifoQueueRequest(ModbusPDU):

220

function_code = 0x18

221

def __init__(self, address=None, slave=0, **kwargs): ...

222

def encode(self) -> bytes: ...

223

def decode(self, data: bytes): ...

224

225

class ReadFifoQueueResponse(ModbusPDU):

226

function_code = 0x18

227

def __init__(self, values=None, **kwargs): ...

228

def encode(self) -> bytes: ...

229

def decode(self, data: bytes): ...

230

```

231

232

### Diagnostic Operations

233

234

PDU messages for diagnostic and status operations.

235

236

```python { .api }

237

# Diagnostic Status (FC 08)

238

class DiagnosticStatusRequest(ModbusPDU):

239

function_code = 0x08

240

def __init__(self, sub_function_code=0x0000, data=None, slave=0, **kwargs): ...

241

def encode(self) -> bytes: ...

242

def decode(self, data: bytes): ...

243

244

class DiagnosticStatusResponse(ModbusPDU):

245

function_code = 0x08

246

def __init__(self, sub_function_code=0x0000, data=None, **kwargs): ...

247

def encode(self) -> bytes: ...

248

def decode(self, data: bytes): ...

249

250

# Read Exception Status (FC 07)

251

class ReadExceptionStatusRequest(ModbusPDU):

252

function_code = 0x07

253

def __init__(self, slave=0, **kwargs): ...

254

def encode(self) -> bytes: ...

255

def decode(self, data: bytes): ...

256

257

class ReadExceptionStatusResponse(ModbusPDU):

258

function_code = 0x07

259

def __init__(self, status=0x00, **kwargs): ...

260

def encode(self) -> bytes: ...

261

def decode(self, data: bytes): ...

262

263

# Get Communication Event Counter (FC 11)

264

class GetCommEventCounterRequest(ModbusPDU):

265

function_code = 0x0B

266

def __init__(self, slave=0, **kwargs): ...

267

def encode(self) -> bytes: ...

268

def decode(self, data: bytes): ...

269

270

class GetCommEventCounterResponse(ModbusPDU):

271

function_code = 0x0B

272

def __init__(self, status=0x0000, count=0x0000, **kwargs): ...

273

def encode(self) -> bytes: ...

274

def decode(self, data: bytes): ...

275

276

# Get Communication Event Log (FC 12)

277

class GetCommEventLogRequest(ModbusPDU):

278

function_code = 0x0C

279

def __init__(self, slave=0, **kwargs): ...

280

def encode(self) -> bytes: ...

281

def decode(self, data: bytes): ...

282

283

class GetCommEventLogResponse(ModbusPDU):

284

function_code = 0x0C

285

def __init__(self, status=0x0000, event_count=0x0000, message_count=0x0000,

286

events=None, **kwargs): ...

287

def encode(self) -> bytes: ...

288

def decode(self, data: bytes): ...

289

```

290

291

### Device Information Operations

292

293

PDU messages for device identification and server information.

294

295

```python { .api }

296

# Report Server ID (FC 17)

297

class ReportServerIdRequest(ModbusPDU):

298

function_code = 0x11

299

def __init__(self, slave=0, **kwargs): ...

300

def encode(self) -> bytes: ...

301

def decode(self, data: bytes): ...

302

303

class ReportServerIdResponse(ModbusPDU):

304

function_code = 0x11

305

def __init__(self, identifier=None, status=0x00, **kwargs): ...

306

def encode(self) -> bytes: ...

307

def decode(self, data: bytes): ...

308

309

# Read Device Information (FC 43)

310

class ReadDeviceInformationRequest(ModbusPDU):

311

function_code = 0x2B

312

def __init__(self, read_code=None, object_id=0x00, slave=0, **kwargs): ...

313

def encode(self) -> bytes: ...

314

def decode(self, data: bytes): ...

315

316

class ReadDeviceInformationResponse(ModbusPDU):

317

function_code = 0x2B

318

def __init__(self, read_code=None, conformity=0x01, more_follows=0x00,

319

next_object_id=0x00, number_of_objects=0x00, information=None, **kwargs): ...

320

def encode(self) -> bytes: ...

321

def decode(self, data: bytes): ...

322

```

323

324

### Device Support Classes

325

326

Supporting classes for device identification and statistics.

327

328

```python { .api }

329

class ModbusDeviceIdentification:

330

def __init__(self, info=None): ...

331

def update(self, value: dict): ...

332

def __getitem__(self, key): ...

333

def __setitem__(self, key, value): ...

334

def __iter__(self): ...

335

def summary(self) -> dict: ...

336

337

class ModbusPlusStatistics:

338

def __init__(self): ...

339

def reset(self): ...

340

def summary(self) -> dict: ...

341

```

342

343

## Usage Examples

344

345

### Direct PDU Usage

346

347

```python

348

from pymodbus.pdu.bit_message import ReadCoilsRequest, ReadCoilsResponse

349

from pymodbus.pdu.register_message import ReadHoldingRegistersRequest

350

351

# Create a read coils request

352

request = ReadCoilsRequest(address=0, count=8, slave=1)

353

encoded_request = request.encode()

354

print(f"Encoded request: {encoded_request.hex()}")

355

356

# Decode the request

357

decoded_request = ReadCoilsRequest()

358

decoded_request.decode(encoded_request)

359

print(f"Address: {decoded_request.address}, Count: {decoded_request.count}")

360

361

# Create a response

362

response = ReadCoilsResponse(values=[True, False, True, True, False, False, True, False])

363

encoded_response = response.encode()

364

print(f"Encoded response: {encoded_response.hex()}")

365

print(f"Coil bits: {response.bits}")

366

```

367

368

### Custom PDU Implementation

369

370

```python

371

from pymodbus.pdu import ModbusPDU

372

import struct

373

374

class CustomReadRequest(ModbusPDU):

375

function_code = 0x40 # Custom function code

376

377

def __init__(self, address=None, count=None, slave=0, **kwargs):

378

ModbusPDU.__init__(self, **kwargs)

379

self.address = address

380

self.count = count

381

self.slave = slave

382

383

def encode(self):

384

return struct.pack('>HH', self.address, self.count)

385

386

def decode(self, data):

387

self.address, self.count = struct.unpack('>HH', data)

388

389

class CustomReadResponse(ModbusPDU):

390

function_code = 0x40

391

392

def __init__(self, values=None, **kwargs):

393

ModbusPDU.__init__(self, **kwargs)

394

self.values = values or []

395

396

def encode(self):

397

result = struct.pack('B', len(self.values))

398

for value in self.values:

399

result += struct.pack('>H', value)

400

return result

401

402

def decode(self, data):

403

count = struct.unpack('B', data[0:1])[0]

404

self.values = []

405

for i in range(count):

406

value = struct.unpack('>H', data[1 + i*2:3 + i*2])[0]

407

self.values.append(value)

408

409

# Usage

410

request = CustomReadRequest(address=100, count=5, slave=1)

411

encoded = request.encode()

412

print(f"Custom request: {encoded.hex()}")

413

414

response = CustomReadResponse(values=[1000, 2000, 3000, 4000, 5000])

415

encoded = response.encode()

416

print(f"Custom response: {encoded.hex()}")

417

```

418

419

### Exception Response Handling

420

421

```python

422

from pymodbus.pdu.exceptionresponse import ExceptionResponse

423

from pymodbus.constants import ExcCodes

424

425

# Create exception response

426

exception = ExceptionResponse(function_code=0x03, exception_code=ExcCodes.ILLEGAL_ADDRESS)

427

encoded = exception.encode()

428

print(f"Exception response: {encoded.hex()}")

429

430

# Decode exception

431

decoded_exception = ExceptionResponse()

432

decoded_exception.decode(encoded)

433

print(f"Function code: {decoded_exception.function_code}")

434

print(f"Exception code: {decoded_exception.exception_code}")

435

```

436

437

### PDU Message Factory

438

439

```python

440

from pymodbus.pdu.decoders import DecodePDU

441

from pymodbus.pdu.bit_message import ReadCoilsRequest

442

from pymodbus.pdu.register_message import ReadHoldingRegistersRequest

443

444

# Register message types

445

DecodePDU.register(ReadCoilsRequest)

446

DecodePDU.register(ReadHoldingRegistersRequest)

447

448

# Create and encode different message types

449

coil_request = ReadCoilsRequest(address=0, count=10, slave=1)

450

register_request = ReadHoldingRegistersRequest(address=100, count=5, slave=2)

451

452

# Decode messages dynamically

453

decoder = DecodePDU()

454

decoded_coil = decoder.decode(coil_request.encode())

455

decoded_register = decoder.decode(register_request.encode())

456

457

print(f"Decoded coil request: FC={decoded_coil.function_code}, addr={decoded_coil.address}")

458

print(f"Decoded register request: FC={decoded_register.function_code}, addr={decoded_register.address}")

459

```

460

461

### File Record Operations

462

463

```python

464

from pymodbus.pdu.file_message import FileRecord, ReadFileRecordRequest, WriteFileRecordRequest

465

466

# Create file records

467

records_to_read = [

468

FileRecord(file_number=1, record_number=0, record_data=None),

469

FileRecord(file_number=1, record_number=1, record_data=None)

470

]

471

472

# Read file record request

473

read_request = ReadFileRecordRequest(records=records_to_read, slave=1)

474

encoded_read = read_request.encode()

475

print(f"Read file record request: {encoded_read.hex()}")

476

477

# Write file record request

478

records_to_write = [

479

FileRecord(file_number=1, record_number=0, record_data=[0x1234, 0x5678])

480

]

481

write_request = WriteFileRecordRequest(records=records_to_write, slave=1)

482

encoded_write = write_request.encode()

483

print(f"Write file record request: {encoded_write.hex()}")

484

```

485

486

### Device Information Queries

487

488

```python

489

from pymodbus.pdu.mei_message import ReadDeviceInformationRequest

490

from pymodbus import ModbusDeviceIdentification

491

492

# Read device information request

493

device_info_request = ReadDeviceInformationRequest(read_code=0x01, object_id=0x00, slave=1)

494

encoded = device_info_request.encode()

495

print(f"Device info request: {encoded.hex()}")

496

497

# Create device identification

498

device_id = ModbusDeviceIdentification()

499

device_id.VendorName = 'PyModbus'

500

device_id.ProductCode = 'PM'

501

device_id.VendorUrl = 'http://github.com/riptideio/pymodbus/'

502

device_id.ProductName = 'PyModbus Server'

503

device_id.ModelName = 'PyModbus Server'

504

device_id.MajorMinorRevision = '3.11.1'

505

506

print(f"Device identification: {device_id.summary()}")

507

```