plc와 pc 연동을 C#, python으로 구현해보고, npm에 modbus-serial 모듈이 있는 것을 알고 난 후 nodejs를 활용하여 plc와의 연동을 테스트해보았다.
예제 코드도 가지고 있었던 터라 아무 문제 없이 해결할 수 있을 줄 알았지만 예상치 못한 문제가 발생하였다.
Issue
콜백 함수의 향연으로 Thread를 신경쓰지 않아도 되는 nodejs 특성상 어떤 놈이 먼저 실행이 될 지 알 수가 없다...ㅋ
그러다 보니 serial 통신을 이용해서 하나의 데이터만 가져오는 것은 아무 상관이 없었는데, read를 두 번 이상 하니 이 함수 놈이 요청하고, serial통신 버퍼에 있는 데이터를 몽땅 가져오는 바람에 뒤에 실행되는 read함수에서 데이터가 없다며 에러를 토해내는 것이 아닌가..
그렇다면 내가 할 수 있는 최선은 이 중구난방으로 실행되는 비동기 함수들을 순차적으로 실행시켜주면 되는 일..
그래서 Async.series를 사용해서 문제를 해결하였다.
p.s. series는 단순 순차 실행, waterfall은 순차 실행인데 결과를 다음 콜백 함수에 전달 할 수 있다고 한다더라.
해결
개발 환경 : Ubuntu 64bit 16.04
IDE : vscode
nodejs version : v13.11.0
npm package : modbus-serial , async
더보기
코드
const ModbusRTU = require ("modbus-serial" )
var async = require ("async" );
var client = new ModbusRTU();
var timeoutConnectRef = null
function connect ( ) {
console .log("Connecting..!!" );
clearTimeout (timeoutConnectRef);
if (client.isOpen){
console .log('Already connected!!' );
run();
}
client.connectRTUBuffered("/dev/ttyUSB0" , {dataBits : 8 , stopBits : 1 , baudRate : 115200 })
.then(setClient)
.then(function ( ) {console .log("Connected" );})
}
function setClient ( ) {
console .log("Set client ID..!!" );
client.setID(1 );
client.setTimeout(3000 );
run();
}
var task = [
function (callback ) {
client.readDiscreteInputs(1 ,4 , function (err, res_read ) {
console .log("L1: " ,res_read.data[0 ], res_read.data[1 ], res_read.data[2 ], res_read.data[3 ])
callback()
})
},
function (callback ) {
client.readHoldingRegisters(1 ,4 , function (err, res_read ) {
console .log("L1Q: " ,res_read.data[0 ], res_read.data[1 ], res_read.data[2 ], res_read.data[3 ])
callback()
})
}
]
function run ( ) {
var setLoop = setInterval (function ( ) {
async .series(task, function (err, results ) {
console .log("done" )
})
}, 1000 )
}
connect()
출력 결과
ㅣ1은 bit를, L1Q는 word를 읽는 것.
github : https://github.com/Mistive/-js-modbusRTU.git
task 변수를 생성하여 순차적으로 동작시킬 task를 설정해주고, 1초에 한번씩 위의 동작을 반복하여 내가 필요한 값을 읽어들이는 작업을 수행하였다.
처음에 callback()을 function(callback){} 안에 넣지 않고 밖에 넣었더니 순차적으로 진행이 되지 않는 실수를..ㅎ;;
1번의 콜백 함수가 호출이 된 후, 콜백 함수가 수행이 되고, 1의 결과를 출력하고 그 다음 콜백 함수를 수행하는 형식으로 동작한다.
이거야 함수가 2개밖에 안되서 콜백에 콜백을 써도 되겠지만..... 한 3~4개만 되도 보는 사람 빡치게 만들기 충분한 코드가 될 것이라고 확답할 수 있다..ㅎㅎ
python으로 구현할 때는 thread timer를 이용하여 일정 주기로 Read&Write를 수행했는데, 흠.... js가 좀 더 깔끔한거 같기도 하고...ㅎㅎ
무튼 재밌다 코딩 ㅋㅋ