Skip to content

Commit

Permalink
feat(opchda): Use OIBus Agent for OPCHDA queries
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerni10 committed Nov 6, 2023
1 parent 1ad8db1 commit 5f19d30
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 96 deletions.
19 changes: 1 addition & 18 deletions backend/src/repository/south-connector.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,7 @@ export default class SouthConnectorRepository {
overlap: result.overlap
},
settings: JSON.parse(result.settings)
}))
.filter(result =>
[
'ads',
'folder-scanner',
'modbus',
'mqtt',
'mssql',
'mysql',
'odbc',
'oianalytics',
'opcua',
'oracle',
'postgresql',
'slims',
'sqlite'
].includes(result.type)
);
}));
}

/**
Expand Down
9 changes: 5 additions & 4 deletions backend/src/service/south.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import RepositoryService from './repository.service';
// South imports
import SouthFolderScanner from '../south/south-folder-scanner/south-folder-scanner';
import SouthOPCUA from '../south/south-opcua/south-opcua';
// import SouthOPCHDA from '../south/south-opchda/south-opchda';
import SouthMQTT from '../south/south-mqtt/south-mqtt';
import SouthMSSQL from '../south/south-mssql/south-mssql';
import SouthMySQL from '../south/south-mysql/south-mysql';
Expand All @@ -16,14 +15,15 @@ import SouthSQLite from '../south/south-sqlite/south-sqlite';
import SouthADS from '../south/south-ads/south-ads';
import SouthModbus from '../south/south-modbus/south-modbus';
import SouthOIAnalytics from '../south/south-oianalytics/south-oianalytics';
import SouthSlims from '../south/south-slims/south-slims';
import SouthOPCHDA from '../south/south-opchda/south-opchda';

import { SouthConnectorDTO, SouthConnectorItemDTO, SouthConnectorManifest } from '../../../shared/model/south-connector.model';
import SouthConnector from '../south/south-connector';
import SouthSlims from '../south/south-slims/south-slims';

import oianalyticsManifest from '../south/south-oianalytics/manifest';
import slimsManifest from '../south/south-slims/manifest';
import opcuaManifest from '../south/south-opcua/manifest';
// import opchdaManifest from '../south/south-opchda/manifest';
import mqttManifest from '../south/south-mqtt/manifest';
import modbusManifest from '../south/south-modbus/manifest';
import folderScannerManifest from '../south/south-folder-scanner/manifest';
Expand All @@ -34,12 +34,13 @@ import postgresqlManifest from '../south/south-postgresql/manifest';
import oracleManifest from '../south/south-oracle/manifest';
import odbcManifest from '../south/south-odbc/manifest';
import sqliteManifest from '../south/south-sqlite/manifest';
import opchdaManifest from '../south/south-opchda/manifest';

const southList: Array<{ class: typeof SouthConnector<any, any>; manifest: SouthConnectorManifest }> = [
{ class: SouthFolderScanner, manifest: folderScannerManifest },
{ class: SouthMQTT, manifest: mqttManifest },
{ class: SouthOPCUA, manifest: opcuaManifest },
// { class: SouthOPCHDA, manifest: opchdaManifest },
{ class: SouthOPCHDA, manifest: opchdaManifest },
{ class: SouthMSSQL, manifest: mssqlManifest },
{ class: SouthMySQL, manifest: mysqlManifest },
{ class: SouthODBC, manifest: odbcManifest },
Expand Down
39 changes: 27 additions & 12 deletions backend/src/south/south-opchda/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const manifest: SouthConnectorManifest = {
type: 'OibText',
label: 'Remote agent URL',
defaultValue: 'http://ip-adress-or-host:2224',
validators: [{ key: 'required' }]
validators: [{ key: 'required' }],
displayInViewMode: true
},
{
key: 'retryInterval',
Expand All @@ -30,20 +31,31 @@ const manifest: SouthConnectorManifest = {
validators: [{ key: 'required' }, { key: 'min', params: { min: 100 } }, { key: 'max', params: { max: 30_000 } }]
},
{
key: 'serverUrl',
key: 'host',
type: 'OibText',
label: 'Server URL (from the agent)',
defaultValue: 'opchda://domain.name/Matrikon.OPC.Simulation',
defaultValue: 'localhost',
class: 'col-4',
newRow: true,
validators: [{ key: 'required' }],
displayInViewMode: false
displayInViewMode: true
},
{
key: 'serverName',
type: 'OibText',
label: 'Server name',
defaultValue: 'Matrikon.OPC.Simulation',
class: 'col-4',
newRow: false,
validators: [{ key: 'required' }],
displayInViewMode: true
},
{
key: 'readTimeout',
type: 'OibNumber',
label: 'Read timeout (s)',
defaultValue: 180,
class: 'col-3',
class: 'col-2',
newRow: false,
validators: [{ key: 'required' }, { key: 'min', params: { min: 100 } }, { key: 'max', params: { max: 3_600_000 } }],
displayInViewMode: false
Expand All @@ -53,7 +65,7 @@ const manifest: SouthConnectorManifest = {
type: 'OibNumber',
label: 'Max return values',
defaultValue: 1000,
class: 'col-3',
class: 'col-2',
newRow: false,
validators: [{ key: 'required' }],
displayInViewMode: false
Expand All @@ -76,19 +88,22 @@ const manifest: SouthConnectorManifest = {
key: 'aggregate',
type: 'OibSelect',
label: 'Aggregate',
options: ['Raw', 'Average', 'Minimum', 'Maximum', 'Count'],
defaultValue: 'Raw',
pipe: 'aggregates',
options: ['raw', 'average', 'minimum', 'maximum'],
defaultValue: 'raw',
validators: [{ key: 'required' }],
displayInViewMode: true
},
{
key: 'resampling',
type: 'OibSelect',
label: 'Resampling',
options: ['None', 'Second', '10 Seconds', '30 Seconds', 'Minute', 'Hour', 'Day'],
defaultValue: 'None',
displayInViewMode: true,
validators: [{ key: 'required' }]
pipe: 'resampling',
options: ['none', 'second', '10Seconds', '30Seconds', 'minute', 'hour', 'day'],
defaultValue: 'none',
validators: [{ key: 'required' }],
conditionalDisplay: { field: 'aggregate', values: ['average', 'minimum', 'maximum', 'count'] },
displayInViewMode: true
}
]
}
Expand Down
50 changes: 36 additions & 14 deletions backend/src/south/south-opchda/south-opchda.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ const items: Array<SouthConnectorItemDTO<SouthOPCHDAItemSettings>> = [
connectorId: 'southId',
settings: {
nodeId: 'ns=3;s=Random',
aggregate: 'Raw',
resampling: 'None'
aggregate: 'raw',
resampling: 'none'
},
scanModeId: 'scanModeId1'
},
Expand All @@ -72,8 +72,7 @@ const items: Array<SouthConnectorItemDTO<SouthOPCHDAItemSettings>> = [
connectorId: 'southId',
settings: {
nodeId: 'ns=3;s=Counter',
aggregate: 'Raw',
resampling: 'None'
aggregate: 'raw'
},
scanModeId: 'scanModeId1'
},
Expand All @@ -84,8 +83,8 @@ const items: Array<SouthConnectorItemDTO<SouthOPCHDAItemSettings>> = [
connectorId: 'southId',
settings: {
nodeId: 'ns=3;s=Triangle',
aggregate: 'Raw',
resampling: 'None'
aggregate: 'average',
resampling: '10Seconds'
},
scanModeId: 'scanModeId2'
}
Expand All @@ -108,7 +107,8 @@ const configuration: SouthConnectorDTO<SouthOPCHDASettings> = {
retryInterval: 1000,
maxReturnValues: 0,
readTimeout: 60,
serverUrl: 'opchda://localhost/Matrikon.OPC.Simulation'
host: 'localhost',
serverName: 'Matrikon.OPC.Simulation'
}
};
let south: SouthOPCHDA;
Expand All @@ -126,7 +126,8 @@ describe('South OPCHDA', () => {
expect(fetch).toHaveBeenCalledWith(`${configuration.settings.agentUrl}/api/opc/${configuration.id}/connect`, {
method: 'PUT',
body: JSON.stringify({
url: configuration.settings.serverUrl
host: configuration.settings.host,
serverName: configuration.settings.serverName
}),
headers: {
'Content-Type': 'application/json'
Expand All @@ -148,7 +149,8 @@ describe('South OPCHDA', () => {
expect(fetch).toHaveBeenCalledWith(`${configuration.settings.agentUrl}/api/opc/${configuration.id}/connect`, {
method: 'PUT',
body: JSON.stringify({
url: configuration.settings.serverUrl
host: configuration.settings.host,
serverName: configuration.settings.serverName
}),
headers: {
'Content-Type': 'application/json'
Expand Down Expand Up @@ -197,7 +199,7 @@ describe('South OPCHDA', () => {
await south.testConnection();
expect(logger.info).toHaveBeenCalledWith('Connected to remote OPC server. Disconnecting...');
expect(logger.info).toHaveBeenCalledWith(
`Testing OPC OIBus Agent connection on ${configuration.settings.agentUrl} with "${configuration.settings.serverUrl}"`
`Testing OPC OIBus Agent connection on ${configuration.settings.agentUrl} with host "${configuration.settings.host}" and server name "${configuration.settings.serverName}"`
);
});

Expand Down Expand Up @@ -258,9 +260,32 @@ describe('South OPCHDA', () => {
expect(fetch).toHaveBeenCalledWith(`${configuration.settings.agentUrl}/api/opc/${configuration.id}/read`, {
method: 'PUT',
body: JSON.stringify({
host: configuration.settings.host,
serverName: configuration.settings.serverName,
aggregate: 'raw',
resampling: 'none',
startTime,
endTime,
items
items: [
{ name: 'item1', nodeId: 'ns=3;s=Random' },
{ name: 'item2', nodeId: 'ns=3;s=Counter' }
]
}),
headers: {
'Content-Type': 'application/json'
}
});

expect(fetch).toHaveBeenCalledWith(`${configuration.settings.agentUrl}/api/opc/${configuration.id}/read`, {
method: 'PUT',
body: JSON.stringify({
host: configuration.settings.host,
serverName: configuration.settings.serverName,
aggregate: 'average',
resampling: '10Seconds',
startTime,
endTime,
items: [{ name: 'item3', nodeId: 'ns=3;s=Triangle' }]
}),
headers: {
'Content-Type': 'application/json'
Expand All @@ -270,7 +295,6 @@ describe('South OPCHDA', () => {
expect(result).toEqual('2020-03-01T00:00:00.000Z');
expect(south.addValues).toHaveBeenCalledWith([{ timestamp: '2020-02-01T00:00:00.000Z' }, { timestamp: '2020-03-01T00:00:00.000Z' }]);

await south.historyQuery(items, startTime, endTime);
expect(logger.debug).toHaveBeenCalledWith(`No result found. Request done in 0 ms`);
});

Expand All @@ -293,8 +317,6 @@ describe('South OPCHDA', () => {

await south.historyQuery(items, startTime, endTime);
expect(logger.error).toHaveBeenCalledWith(`Error occurred when querying remote agent with status 400: bad request`);

await south.historyQuery(items, startTime, endTime);
expect(logger.error).toHaveBeenCalledWith(`Error occurred when querying remote agent with status 500`);
});
});
Loading

0 comments on commit 5f19d30

Please sign in to comment.