A Go library for communicating with Mitsubishi PLCs using the MC Protocol (SLMP).
- 3E frame — TCP and UDP transport, Binary and ASCII mode
- 4E frame — TCP, Binary and ASCII mode, with serial number tracking
- Batch read/write: words and bits
- Random read/write: multiple devices in a single request
- Remote control: Run, Stop, Pause, Latch Clear, Reset
- Goroutine-safe: requests on the same client instance are serialized internally
A REST API wrapper for this library is available at Moge800/gomc-rest. Use it when you want to expose MC Protocol communication over HTTP from another application or service.
go get github.com/moge800/gomcprotocolimport "github.com/moge800/gomcprotocol"package main
import (
"fmt"
mc "github.com/moge800/gomcprotocol"
)
func main() {
c, err := mc.New3EClient("192.168.0.1", 5007, mc.ModeBinary)
if err != nil {
panic(err)
}
if err := c.Connect(); err != nil {
panic(err)
}
defer c.Close()
// Read 5 words from D100
words, err := c.ReadWords("D", 100, 5)
if err != nil {
panic(err)
}
fmt.Println(words)
// Write to D200
if err := c.WriteWords("D", 200, []uint16{1, 2, 3}); err != nil {
panic(err)
}
}c, err := mc.New3EClientUDP("192.168.0.1", 5007, mc.ModeBinary)c, err := mc.New4EClient("192.168.0.1", 5007, mc.ModeBinary)| Method | Description |
|---|---|
New3EClient(host, port, mode) |
Create a 3E TCP client |
New3EClientUDP(host, port, mode) |
Create a 3E UDP client |
Connect() |
Establish connection |
Close() |
Close connection |
ReadWords(device, start, count) |
Read word values |
WriteWords(device, start, values) |
Write word values |
ReadBits(device, start, count) |
Read bit values |
WriteBits(device, start, values) |
Write bit values |
RandomRead(words, dwords) |
Read multiple devices at once |
RandomWrite(words, wordVals, dwords, dwordVals) |
Write multiple devices at once |
RandomWriteBits(devices, values) |
Write multiple bit devices at once |
RemoteRun(clearMode, force) |
Start PLC remotely |
RemoteStop() |
Stop PLC remotely |
RemotePause(force) |
Pause PLC remotely |
RemoteLatchClear() |
Clear latch (PLC must be stopped) |
RemoteReset() |
Reset PLC (connection will close) |
Client4E provides the same methods as Client3E, created via New4EClient.
Requests issued concurrently on the same client instance are serialized internally, so only one MC Protocol request/response exchange is active on that connection at a time.
| Constant | Description |
|---|---|
ModeBinary |
Binary framing (compact, recommended) |
ModeASCII |
ASCII framing (human-readable) |
| Device | Type | Notes |
|---|---|---|
D |
Word | Data register |
W |
Word | Link register |
R |
Word | File register |
ZR |
Word | File register (extended) |
SW |
Word | Link special register |
TN |
Word | Timer current value |
STN |
Word | Retentive timer current value |
CN |
Word | Counter current value |
Z |
Word | Index register |
X |
Bit | Input |
Y |
Bit | Output |
M |
Bit | Internal relay |
L |
Bit | Latch relay |
V |
Bit | Edge relay |
S |
Bit | Step relay |
DX |
Bit | Direct access input |
DY |
Bit | Direct access output |
TC |
Bit | Timer coil |
TS |
Bit | Timer contact |
STC |
Bit | Retentive timer coil |
STS |
Bit | Retentive timer contact |
CC |
Bit | Counter coil |
CS |
Bit | Counter contact |
B |
Bit | Link relay |
F |
Bit | Annunciator |
SB |
Bit | Link special relay |
SM |
Bit | Special relay |
SD |
Word | Special register |
Device names are case-insensitive ("d" and "D" both work).
// Read D100 (word) and D200 (word) and D300 (dword) in one request
words, dwords, err := c.RandomRead(
[]mc.DeviceAddr{{"D", 100}, {"D", 200}},
[]mc.DeviceAddr{{"D", 300}},
)
// Write D100=10, D200=20 (words) and D300=100000 (dword)
err = c.RandomWrite(
[]mc.DeviceAddr{{"D", 100}, {"D", 200}},
[]uint16{10, 20},
[]mc.DeviceAddr{{"D", 300}},
[]uint32{100000},
)
// Write bits to M0, M10, Y5
err = c.RandomWriteBits(
[]mc.DeviceAddr{{"M", 0}, {"M", 10}, {"Y", 5}},
[]bool{true, false, true},
)words, err := c.ReadWords("D", 100, 5)
if err != nil {
if mcErr, ok := err.(*mc.MCProtocolError); ok {
// PLC returned a non-zero end code
fmt.Printf("PLC error: 0x%04X\n", mcErr.EndCode)
} else {
// Network or connection error
fmt.Println("connection error:", err)
}
}The PLC must have Ethernet communication enabled with SLMP (MC Protocol) configured.
Default port is typically 5007 for Q/iQ-R series.
Runnable examples are in the examples/ directory:
| Directory | Description |
|---|---|
01_basic_read |
Read word devices (minimal) |
02_basic_write |
Write words and read back |
03_bit_operations |
Read/write bit devices (X, M, Y) |
04_random_access |
RandomRead/RandomWrite across multiple devices |
05_remote_control |
Stop → LatchClear → Run sequence |
06_monitor |
Polling loop with change detection and auto-reconnect |
MIT