mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-10-10 16:43:35 +02:00
2017-05-03 Fred Gleason <fredg@paravelsystems.com>
* Added an 'RDMatrix::Modbus' element to the 'RDMatrix::Type enum. * Implemented a Modbus TCP switcher driver in 'ripcd/modbus.cpp' and 'ripcd/modbus.h'.
This commit is contained in:
@@ -15754,3 +15754,7 @@
|
||||
2017-05-02 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Fixed a bug that caused RDCartSlots to fail to rotate cuts when
|
||||
replaying a cart without a reload.
|
||||
2017-05-03 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Added an 'RDMatrix::Modbus' element to the 'RDMatrix::Type enum.
|
||||
* Implemented a Modbus TCP switcher driver in 'ripcd/modbus.cpp' and
|
||||
'ripcd/modbus.h'.
|
||||
|
@@ -24,6 +24,7 @@ LiveWire LWRP GPIO
|
||||
LiveWire Multicast GPIO
|
||||
Local Audio Adapter
|
||||
Logitek vGuest
|
||||
Modbus TCP
|
||||
Quartz Electronics Type 1 Routing Protocol
|
||||
Ross NK Video Switchers (via SCP/A Serial Interface)
|
||||
Serial Port Modem Control Lines
|
||||
@@ -580,6 +581,19 @@ such as faders feeds, not just GPIO) are mapped to logical Rivendell
|
||||
GPIO lines by means of their Logitek Engine, Device and Buss numbers.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Driver Name: Modbus TCP
|
||||
|
||||
Supported RML Commands:
|
||||
GPI Enable ('GE')
|
||||
GPI Set ('GI')
|
||||
|
||||
GENERAL NOTES:
|
||||
This driver supports GPI devices that use the industry-standard Modbus TCP
|
||||
protocol at TCP port 502. The device to be controlled should be configured
|
||||
to use Modbus ID #1. For more information on Modbus, see http://www.modbus.org/.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Quartz Electronics Type 1 Routing Protocol
|
||||
|
||||
|
@@ -66,7 +66,8 @@ bool __mx_primary_controls[RDMatrix::LastType][RDMatrix::LastControl]=
|
||||
{0,1,1,1,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0}, // SAS 16000
|
||||
{0,1,0,0,0,0,0,0,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0}, // Ross NK/SCP
|
||||
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT ADMS 44.22
|
||||
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0} // BT SS 4.1 MLR
|
||||
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR
|
||||
{0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // Modbus
|
||||
};
|
||||
bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]=
|
||||
{
|
||||
@@ -109,7 +110,8 @@ bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]=
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // SAS 16000
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // ROSS NK/SCP
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT ADMS 44.22
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // BT SS 4.1 MLR
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Modbus
|
||||
};
|
||||
|
||||
int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]=
|
||||
@@ -153,7 +155,8 @@ int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]=
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // SAS 16000
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Ross NK/SCP
|
||||
{0,0,0,0,0,0,0,0,0,0,0,8,2,16,13,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT ADMS 44.22
|
||||
{0,0,0,0,0,0,0,0,0,0,0,4,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // BT SS 4.1 MLR
|
||||
{0,0,0,0,0,0,0,0,0,0,0,4,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT SS 4.1 MLR
|
||||
{1,0,0,502,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // Modbus
|
||||
};
|
||||
|
||||
RDMatrix::RDMatrix(const QString &station,int matrix)
|
||||
@@ -717,6 +720,10 @@ QString RDMatrix::typeString(RDMatrix::Type type)
|
||||
return QString("BroadcastTools SS 4.1 MLR");
|
||||
break;
|
||||
|
||||
case RDMatrix::Modbus:
|
||||
return QString("Modbus TCP");
|
||||
break;
|
||||
|
||||
default:
|
||||
return QString("Unknown Type");
|
||||
break;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Abstract a Rivendell Switcher Matrix
|
||||
//
|
||||
// (C) Copyright 2002-2016 Fred Gleason <fredg@paravelsystems.com>
|
||||
// (C) Copyright 2002-2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@@ -38,7 +38,7 @@ class RDMatrix
|
||||
BtSrc16=24,Harlond=25,Acu1p=26,LiveWireMcastGpio=27,Am16=28,
|
||||
LiveWireLwrpGpio=29,BtSentinel4Web=30,BtGpi16=31,ModemLines=32,
|
||||
SoftwareAuthority=33,Sas16000=34,RossNkScp=35,BtAdms4422=36,
|
||||
BtSs41Mlr=37,LastType=38};
|
||||
BtSs41Mlr=37,Modbus=38,LastType=39};
|
||||
enum Endpoint {Input=0,Output=1};
|
||||
enum Mode {Stereo=0,Left=1,Right=2};
|
||||
enum VguestAttribute {VguestEngine=0,VguestDevice=1,VguestSurface=2,
|
||||
|
@@ -57,6 +57,7 @@ dist_ripcd_SOURCES = acu1p.cpp acu1p.h\
|
||||
local_gpio.cpp local_gpio.h\
|
||||
local_macros.cpp maint_routines.cpp\
|
||||
loaddrivers.cpp\
|
||||
modbus.cpp modbus.h\
|
||||
modemlines.cpp modemlines.h\
|
||||
quartz1.cpp quartz1.h\
|
||||
ripcd.cpp ripcd.h globals.h\
|
||||
@@ -100,6 +101,7 @@ nodist_ripcd_SOURCES = moc_am16.cpp\
|
||||
moc_livewire_mcastgpio.cpp\
|
||||
moc_local_audio.cpp\
|
||||
moc_local_gpio.cpp\
|
||||
moc_modbus.cpp\
|
||||
moc_modemlines.cpp\
|
||||
moc_quartz1.cpp\
|
||||
moc_ripcd.cpp\
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include <livewire_mcastgpio.h>
|
||||
#include <local_audio.h>
|
||||
#include <local_gpio.h>
|
||||
#include <modbus.h>
|
||||
#include <modemlines.h>
|
||||
#include <quartz1.h>
|
||||
#include <rossnkscp.h>
|
||||
@@ -165,6 +166,10 @@ bool MainObject::LoadSwitchDriver(int matrix_num)
|
||||
ripcd_switcher[matrix_num]=new VGuest(matrix,this);
|
||||
break;
|
||||
|
||||
case RDMatrix::Modbus:
|
||||
ripcd_switcher[matrix_num]=new Modbus(matrix,this);
|
||||
break;
|
||||
|
||||
case RDMatrix::ModemLines:
|
||||
ripcd_switcher[matrix_num]=new ModemLines(matrix,this);
|
||||
break;
|
||||
|
250
ripcd/modbus.cpp
Normal file
250
ripcd/modbus.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
// modbus.cpp
|
||||
//
|
||||
// A Rivendell switcher driver for Modbus TCP
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#include "modbus.h"
|
||||
|
||||
Modbus::Modbus(RDMatrix *matrix,QObject *parent)
|
||||
: Switcher(matrix,parent)
|
||||
{
|
||||
modbus_istate=0;
|
||||
modbus_watchdog_active=false;
|
||||
|
||||
modbus_gpis=matrix->gpis();
|
||||
modbus_input_bytes=modbus_gpis/8;
|
||||
if((modbus_gpis%8)!=0) {
|
||||
modbus_input_bytes++;
|
||||
}
|
||||
for(int i=0;i<modbus_input_bytes;i++) {
|
||||
modbus_input_states.push_back(0);
|
||||
}
|
||||
modbus_gpos=matrix->gpos();
|
||||
modbus_ip_address=matrix->ipAddress(RDMatrix::Primary);
|
||||
modbus_ip_port=matrix->ipPort(RDMatrix::Primary);
|
||||
|
||||
modbus_socket=new QSocket(this);
|
||||
connect(modbus_socket,SIGNAL(connected()),this,SLOT(connectedData()));
|
||||
connect(modbus_socket,SIGNAL(readyRead()),this,SLOT(readyReadData()));
|
||||
connect(modbus_socket,SIGNAL(error(int)),this,SLOT(errorData(int)));
|
||||
modbus_socket->connectToHost(modbus_ip_address.toString(),modbus_ip_port);
|
||||
|
||||
modbus_watchdog_timer=new QTimer(this);
|
||||
connect(modbus_watchdog_timer,SIGNAL(timeout()),this,SLOT(watchdogData()));
|
||||
}
|
||||
|
||||
|
||||
Modbus::~Modbus()
|
||||
{
|
||||
delete modbus_watchdog_timer;
|
||||
delete modbus_socket;
|
||||
}
|
||||
|
||||
|
||||
RDMatrix::Type Modbus::type()
|
||||
{
|
||||
return RDMatrix::Modbus;
|
||||
}
|
||||
|
||||
|
||||
unsigned Modbus::gpiQuantity()
|
||||
{
|
||||
return modbus_gpis;
|
||||
}
|
||||
|
||||
|
||||
unsigned Modbus::gpoQuantity()
|
||||
{
|
||||
return modbus_gpos;
|
||||
}
|
||||
|
||||
|
||||
bool Modbus::primaryTtyActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Modbus::secondaryTtyActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Modbus::processCommand(RDMacro *cmd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Modbus::connectedData()
|
||||
{
|
||||
syslog(LOG_INFO,
|
||||
"connection to Modbus device at %s:%u established",
|
||||
(const char *)modbus_ip_address.toString(),0xffff&modbus_ip_port);
|
||||
modbus_watchdog_active=false;
|
||||
PollInputs();
|
||||
}
|
||||
|
||||
|
||||
void Modbus::readyReadData()
|
||||
{
|
||||
char data[1501];
|
||||
int n;
|
||||
char byte;
|
||||
uint16_t len;
|
||||
// char id;
|
||||
char count=0;
|
||||
int base=0;
|
||||
|
||||
while((n=modbus_socket->readBlock(data,1500))>0) {
|
||||
for(int i=0;i<n;i++) {
|
||||
byte=0xff&data[i];
|
||||
switch(modbus_istate) {
|
||||
case 0: // Transaction Identifier
|
||||
modbus_istate=1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
modbus_istate=2;
|
||||
break;
|
||||
|
||||
case 2: // Protocol Identifier
|
||||
if(byte==0) {
|
||||
modbus_istate=3;
|
||||
}
|
||||
else {
|
||||
modbus_istate=0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // Protocol Identifier
|
||||
if(byte==0) {
|
||||
modbus_istate=4;
|
||||
}
|
||||
else {
|
||||
modbus_istate=0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Message Length
|
||||
len=byte<<8;
|
||||
modbus_istate=5;
|
||||
break;
|
||||
|
||||
case 5: // Message Length
|
||||
len+=byte;
|
||||
modbus_istate=6;
|
||||
break;
|
||||
|
||||
case 6: // Modbus ID
|
||||
// id=byte;
|
||||
modbus_istate=7;
|
||||
break;
|
||||
|
||||
case 7: // Function Code
|
||||
if(byte==0x02) {
|
||||
modbus_istate=8;
|
||||
}
|
||||
else {
|
||||
modbus_istate=0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8: // Byte Count
|
||||
count=byte;
|
||||
modbus_istate=9;
|
||||
break;
|
||||
|
||||
case 9: // Input Status
|
||||
base=modbus_input_bytes-count;
|
||||
ProcessInputByte(byte,base);
|
||||
if(--count==0) {
|
||||
PollInputs();
|
||||
modbus_istate=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Modbus::errorData(int err)
|
||||
{
|
||||
watchdogData();
|
||||
}
|
||||
|
||||
|
||||
void Modbus::watchdogData()
|
||||
{
|
||||
if(!modbus_watchdog_active) {
|
||||
syslog(LOG_WARNING,
|
||||
"connection to Modbus device at %s:%u lost, attempting reconnect",
|
||||
(const char *)modbus_ip_address.toString(),0xffff&modbus_ip_port);
|
||||
modbus_watchdog_active=true;
|
||||
}
|
||||
modbus_socket->close();
|
||||
modbus_socket->connectToHost(modbus_ip_address.toString(),modbus_ip_port);
|
||||
}
|
||||
|
||||
|
||||
void Modbus::ProcessInputByte(char byte,int base)
|
||||
{
|
||||
char mask=byte^modbus_input_states[base];
|
||||
for(int i=0;i<8;i++) {
|
||||
if(((1<<i)&mask)!=0) {
|
||||
int line=8*base+i;
|
||||
if(line<modbus_gpis) {
|
||||
emit gpiChanged(matrixNumber(),line,((1<<i)&byte)!=0);
|
||||
}
|
||||
}
|
||||
}
|
||||
modbus_input_states[base]=byte;
|
||||
}
|
||||
|
||||
|
||||
void Modbus::PollInputs()
|
||||
{
|
||||
printf("HERE1\n");
|
||||
char msg[12];
|
||||
msg[0]=0x88; // Transaction Identifier
|
||||
msg[1]=0x88;
|
||||
|
||||
msg[2]=0x00; // Protocol Identifier
|
||||
msg[3]=0x00;
|
||||
|
||||
msg[4]=0x00; // Message Length
|
||||
msg[5]=0x06;
|
||||
|
||||
msg[6]=0x01; // Modbus ID
|
||||
|
||||
msg[7]=0x02; // Function Code (Read Discrete Input)
|
||||
|
||||
msg[8]=0x00; // Starting Address
|
||||
msg[9]=0x00;
|
||||
|
||||
msg[10]=0xff&(modbus_gpis>>8); // Quantity of Inputs
|
||||
msg[11]=0xff&modbus_gpis;
|
||||
|
||||
modbus_socket->writeBlock(msg,12);
|
||||
modbus_watchdog_timer->stop();
|
||||
modbus_watchdog_timer->start(MODBUS_WATCHDOG_INTERVAL,true);
|
||||
printf("HERE2\n");
|
||||
}
|
72
ripcd/modbus.h
Normal file
72
ripcd/modbus.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// modbus.h
|
||||
//
|
||||
// A Rivendell switcher driver for Modbus TCP
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public
|
||||
// License along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
#ifndef MODBUS_H
|
||||
#define MODBUS_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <qsocket.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#include <rd.h>
|
||||
#include <rdmatrix.h>
|
||||
#include <rdmacro.h>
|
||||
|
||||
#include <switcher.h>
|
||||
|
||||
#define MODBUS_WATCHDOG_INTERVAL 1000
|
||||
|
||||
class Modbus : public Switcher
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Modbus(RDMatrix *matrix,QObject *parent=0);
|
||||
~Modbus();
|
||||
RDMatrix::Type type();
|
||||
unsigned gpiQuantity();
|
||||
unsigned gpoQuantity();
|
||||
bool primaryTtyActive();
|
||||
bool secondaryTtyActive();
|
||||
void processCommand(RDMacro *cmd);
|
||||
|
||||
private slots:
|
||||
void connectedData();
|
||||
void readyReadData();
|
||||
void errorData(int err);
|
||||
void watchdogData();
|
||||
|
||||
private:
|
||||
void ProcessInputByte(char byte,int base);
|
||||
void PollInputs();
|
||||
int modbus_istate;
|
||||
int modbus_input_bytes;
|
||||
std::vector<char> modbus_input_states;
|
||||
QSocket *modbus_socket;
|
||||
QTimer *modbus_watchdog_timer;
|
||||
bool modbus_watchdog_active;
|
||||
QHostAddress modbus_ip_address;
|
||||
uint16_t modbus_ip_port;
|
||||
int modbus_gpis;
|
||||
int modbus_gpos;
|
||||
};
|
||||
|
||||
|
||||
#endif // MODBUS_H
|
Reference in New Issue
Block a user