Skip to content

Commit

Permalink
fix(modbus): fix modbus item data model for optional fields
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerni10 committed Jun 10, 2024
1 parent 314f8ff commit a228601
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 57 deletions.
65 changes: 64 additions & 1 deletion backend/src/db/entity-migrations/v3.3.7-add-oia-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,80 @@ import { Knex } from 'knex';
import { OIANALYTICS_MESSAGE_TABLE } from '../../repository/oianalytics-message.repository';
import { ENGINES_TABLE } from '../../repository/engine.repository';
import { version } from '../../../package.json';
import CreateTableBuilder = Knex.CreateTableBuilder;
import { OIANALYTICS_MESSAGE_STATUS } from '../../../../shared/model/oianalytics-message.model';
import CreateTableBuilder = Knex.CreateTableBuilder;
import { SOUTH_CONNECTORS_TABLE } from '../../repository/south-connector.repository';
import { SOUTH_ITEMS_TABLE } from '../../repository/south-item.repository';

const SOUTH_MODBUS_ITEM_SETTINGS_MODBUS_TYPES = ['coil', 'discreteInput', 'inputRegister', 'holdingRegister'] as const;
export type SouthModbusItemSettingsModbusType = (typeof SOUTH_MODBUS_ITEM_SETTINGS_MODBUS_TYPES)[number];

const SOUTH_MODBUS_ITEM_SETTINGS_DATA_DATA_TYPES = [
'Bit',
'UInt16',
'Int16',
'UInt32',
'Int32',
'BigUInt64',
'BigInt64',
'Float',
'Double'
] as const;
export type SouthModbusItemSettingsDataDataType = (typeof SOUTH_MODBUS_ITEM_SETTINGS_DATA_DATA_TYPES)[number];

interface OldSouthModbusItemSettings {
address: string;
modbusType: SouthModbusItemSettingsModbusType;
dataType: SouthModbusItemSettingsDataDataType;
multiplierCoefficient: number;
bitIndex: number;
}

interface NewSouthModbusItemSettings {
address: string;
modbusType: SouthModbusItemSettingsModbusType;
data: {
dataType: SouthModbusItemSettingsDataDataType;
multiplierCoefficient: number;
bitIndex: number;
};
}

function createDefaultEntityFields(table: CreateTableBuilder): void {
table.uuid('id').primary();
table.timestamps(false, true);
}

async function updateModbusItems(knex: Knex) {
const modbusConnectors: Array<{ id: string }> = await knex(SOUTH_CONNECTORS_TABLE).select('id').where('type', 'modbus');

for (const { id } of modbusConnectors) {
const modbusConnectorItems: Array<{ id: string; settings: string }> = await knex(SOUTH_ITEMS_TABLE)
.select('id', 'settings')
.where('connector_id', id);

for (const item of modbusConnectorItems) {
const oldSettings: OldSouthModbusItemSettings = JSON.parse(item.settings);
const newSettings: NewSouthModbusItemSettings = {
address: oldSettings.address,
modbusType: oldSettings.modbusType,
data: {
dataType: oldSettings.dataType,
multiplierCoefficient: oldSettings.multiplierCoefficient,
bitIndex: oldSettings.bitIndex
}
};
await knex(SOUTH_ITEMS_TABLE)
.update({ settings: JSON.stringify(newSettings) })
.where('id', item.id);
}
}
}

export async function up(knex: Knex): Promise<void> {
await createOIAMessageTable(knex);
await addVersionInEngineSettings(knex);
await updateModbusItems(knex);
}

async function createOIAMessageTable(knex: Knex): Promise<void> {
Expand Down
57 changes: 33 additions & 24 deletions backend/src/south/south-modbus/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,32 +115,41 @@ const manifest: SouthConnectorManifest = {
displayInViewMode: true
},
{
key: 'dataType',
type: 'OibSelect',
options: ['Bit', 'UInt16', 'Int16', 'UInt32', 'Int32', 'BigUInt64', 'BigInt64', 'Float', 'Double'],
label: 'Data Type',
defaultValue: 'UInt16',
validators: [{ key: 'required' }],
conditionalDisplay: { field: 'modbusType', values: ['inputRegister', 'holdingRegister'] },
displayInViewMode: false
},
{
key: 'bitIndex',
type: 'OibNumber',
label: 'Bit Index',
defaultValue: 1,
validators: [{ key: 'required' }, { key: 'min', params: { min: 0 } }, { key: 'max', params: { max: 15 } }],
conditionalDisplay: { field: 'dataType', values: ['Bit'] },
displayInViewMode: false
},
{
key: 'multiplierCoefficient',
type: 'OibNumber',
label: 'Multiplier Coefficient',
defaultValue: 1,
key: 'data',
type: 'OibFormGroup',
label: '',
newRow: true,
displayInViewMode: false,
validators: [{ key: 'required' }],
conditionalDisplay: { field: 'modbusType', values: ['inputRegister', 'holdingRegister'] },
displayInViewMode: false
content: [
{
key: 'dataType',
type: 'OibSelect',
options: ['UInt16', 'Int16', 'UInt32', 'Int32', 'BigUInt64', 'BigInt64', 'Float', 'Double', 'Bit'],
label: 'Data Type',
defaultValue: 'UInt16',
validators: [{ key: 'required' }],
displayInViewMode: false
},
{
key: 'bitIndex',
type: 'OibNumber',
label: 'Bit Index',
defaultValue: 1,
validators: [{ key: 'required' }, { key: 'min', params: { min: 0 } }, { key: 'max', params: { max: 15 } }],
conditionalDisplay: { field: 'dataType', values: ['Bit'] },
displayInViewMode: false
},
{
key: 'multiplierCoefficient',
type: 'OibNumber',
label: 'Multiplier Coefficient',
defaultValue: 1,
validators: [{ key: 'required' }],
displayInViewMode: false
}
]
}
]
}
Expand Down
45 changes: 25 additions & 20 deletions backend/src/south/south-modbus/south-modbus.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import RepositoryServiceMock from '../../tests/__mocks__/repository-service.mock
import { SouthConnectorDTO, SouthConnectorItemDTO } from '../../../../shared/model/south-connector.model';
import net from 'node:net';
import Stream from 'node:stream';
import { SouthModbusItemSettings } from '../../../../shared/model/south-settings.model';

jest.mock('node:fs/promises');
jest.mock('node:net');
Expand Down Expand Up @@ -66,17 +67,19 @@ const logger: pino.Logger = new PinoLogger();
const encryptionService: EncryptionService = new EncryptionServiceMock('', '');
const repositoryService: RepositoryService = new RepositoryServiceMock();

const items: Array<SouthConnectorItemDTO> = [
const items: Array<SouthConnectorItemDTO<SouthModbusItemSettings>> = [
{
id: 'id1',
name: 'HoldingRegister',
enabled: true,
connectorId: 'southId',
settings: {
modbusType: 'holdingRegister',
dataType: 'UInt16',
address: '0x4E80',
multiplierCoefficient: 1
modbusType: 'holdingRegister',
data: {
dataType: 'UInt16',
multiplierCoefficient: 1
}
},
scanModeId: 'scanModeId1'
},
Expand All @@ -86,10 +89,12 @@ const items: Array<SouthConnectorItemDTO> = [
enabled: true,
connectorId: 'southId',
settings: {
modbusType: 'holdingRegister',
dataType: 'UInt16',
address: '20097',
multiplierCoefficient: 1
modbusType: 'holdingRegister',
data: {
dataType: 'UInt16',
multiplierCoefficient: 1
}
},
scanModeId: 'scanModeId1'
},
Expand All @@ -99,10 +104,12 @@ const items: Array<SouthConnectorItemDTO> = [
enabled: true,
connectorId: 'southId',
settings: {
modbusType: 'inputRegister',
dataType: 'UInt16',
address: '0x3E81',
multiplierCoefficient: 1
modbusType: 'inputRegister',
data: {
dataType: 'UInt16',
multiplierCoefficient: 1
}
},
scanModeId: 'scanModeId1'
},
Expand All @@ -112,10 +119,8 @@ const items: Array<SouthConnectorItemDTO> = [
enabled: true,
connectorId: 'southId',
settings: {
modbusType: 'discreteInput',
dataType: 'UInt16',
address: '0x1E82',
multiplierCoefficient: 1
modbusType: 'discreteInput'
},
scanModeId: 'scanModeId1'
},
Expand All @@ -125,10 +130,8 @@ const items: Array<SouthConnectorItemDTO> = [
enabled: true,
connectorId: 'southId',
settings: {
modbusType: 'coil',
dataType: 'UInt16',
address: '0x0E83',
multiplierCoefficient: 1
modbusType: 'coil'
},
scanModeId: 'scanModeId1'
},
Expand All @@ -138,11 +141,13 @@ const items: Array<SouthConnectorItemDTO> = [
enabled: true,
connectorId: 'southId',
settings: {
modbusType: 'holdingRegister',
dataType: 'Bit',
address: '0x0E88',
bitIndex: 1,
multiplierCoefficient: 1
modbusType: 'holdingRegister',
data: {
dataType: 'Bit',
bitIndex: 1,
multiplierCoefficient: 1
}
},
scanModeId: 'scanModeId1'
}
Expand Down
12 changes: 6 additions & 6 deletions backend/src/south/south-modbus/south-modbus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,17 @@ export default class SouthModbus extends SouthConnector<SouthModbusSettings, Sou
case 'inputRegister':
value = await this.readInputRegister(
address,
item.settings.multiplierCoefficient!,
item.settings.dataType!,
item.settings.bitIndex
item.settings.data!.multiplierCoefficient!,
item.settings.data!.dataType!,
item.settings.data!.bitIndex
);
break;
case 'holdingRegister':
value = await this.readHoldingRegister(
address,
item.settings.multiplierCoefficient!,
item.settings.dataType!,
item.settings.bitIndex
item.settings.data!.multiplierCoefficient!,
item.settings.data!.dataType!,
item.settings.data!.bitIndex
);
break;
default:
Expand Down
16 changes: 10 additions & 6 deletions shared/model/south-settings.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ export type SouthModbusSettingsAddressOffset = (typeof SOUTH_MODBUS_SETTINGS_ADD
const SOUTH_MODBUS_SETTINGS_ENDIANNESSS = ['Big Endian', 'Little Endian'] as const
export type SouthModbusSettingsEndianness = (typeof SOUTH_MODBUS_SETTINGS_ENDIANNESSS)[number];

const SOUTH_MODBUS_ITEM_SETTINGS_DATA_DATA_TYPES = ['Bit', 'UInt16', 'Int16', 'UInt32', 'Int32', 'BigUInt64', 'BigInt64', 'Float', 'Double'] as const
export type SouthModbusItemSettingsDataDataType = (typeof SOUTH_MODBUS_ITEM_SETTINGS_DATA_DATA_TYPES)[number];

const SOUTH_MODBUS_ITEM_SETTINGS_MODBUS_TYPES = ['coil', 'discreteInput', 'inputRegister', 'holdingRegister'] as const
export type SouthModbusItemSettingsModbusType = (typeof SOUTH_MODBUS_ITEM_SETTINGS_MODBUS_TYPES)[number];

const SOUTH_MODBUS_ITEM_SETTINGS_DATA_TYPES = ['Bit', 'UInt16', 'Int16', 'UInt32', 'Int32', 'BigUInt64', 'BigInt64', 'Float', 'Double'] as const
export type SouthModbusItemSettingsDataType = (typeof SOUTH_MODBUS_ITEM_SETTINGS_DATA_TYPES)[number];

const SOUTH_M_Q_T_T_SETTINGS_AUTHENTICATION_TYPES = ['none', 'basic', 'cert'] as const
export type SouthMQTTSettingsAuthenticationType = (typeof SOUTH_M_Q_T_T_SETTINGS_AUTHENTICATION_TYPES)[number];

Expand Down Expand Up @@ -353,6 +353,12 @@ export type SouthSettings =
| SouthSlimsSettings
| SouthSQLiteSettings

export interface SouthModbusItemSettingsData {
dataType: SouthModbusItemSettingsDataDataType;
bitIndex?: number;
multiplierCoefficient: number;
}

export interface SouthMQTTItemSettingsJsonPayloadTimestampPayload {
timestampPath: string;
timestampType: SouthMQTTItemSettingsJsonPayloadTimestampPayloadTimestampType;
Expand Down Expand Up @@ -560,9 +566,7 @@ export interface SouthFolderScannerItemSettings extends BaseSouthItemSettings {
export interface SouthModbusItemSettings extends BaseSouthItemSettings {
address: string;
modbusType: SouthModbusItemSettingsModbusType;
dataType?: SouthModbusItemSettingsDataType;
bitIndex?: number;
multiplierCoefficient?: number;
data?: SouthModbusItemSettingsData;
}

export interface SouthMQTTItemSettings extends BaseSouthItemSettings {
Expand Down

0 comments on commit a228601

Please sign in to comment.