Skip to content

Commit

Permalink
TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT support and support f…
Browse files Browse the repository at this point in the history
…or strings with all char length added (#65)

* -   (PLCHome) Add TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME and DT Support

-   (PLCHome) Support for Strings with all char length

* version fix

* fix for Test and Release

* fix for Test and Release

* fiki fiki

* fix for Test and Release

* fix for Test and Release

* fix for Test and Release

* fix for Test and Release

Co-authored-by: dkleber89 <dkleber89@gmail.com>
  • Loading branch information
PLCHome and dkleber89 committed Mar 20, 2022
1 parent 40b9b0f commit 1ed8f83
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 32 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ This Project is not affilate to Beckhoff in any way

3. On TwinCat 2 Create a Struct and fill in your needed Symbols. Then add this Struct to a GlobalVariableTable.

##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, STRING(80)
##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT, STRING

OPTIONAL: You can create a Variable in root of Struct with the exact name -> ioBrokerResync (Not Casesensitiv and not matter which Type) -> Every time this Variable changes his value the Table get resynced in ioBroker.

4. On TwinCat 3 Create a GlobalVariableTable and fill in your needed Symbols.

##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, STRING(80)
##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT, STRING

OPTIONAL: You can create a Variable in root of Variable Table with the exact name -> ioBrokerResync (Not Casesensitiv and not matter which Type) -> Every time this Variable changes his value the Table get resynced in ioBroker.

Expand Down Expand Up @@ -65,6 +65,11 @@ Upload your *.tpy File from your PLC Project -> Every Time you change something
3. Sync never meant the Dataexchange of the Symbols. Sync is the create or delete the States in ioBroker dependent on the GlobalVariableTable in the PLC.

## Changelog
### 1.5.1 (2022-03-19)

- (PLCHome) Add TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME and DT support
- (PLCHome) Support for strings with all char length

### 1.5.0 (2021-09-28)

- (dkleber89) Process next state in list when register subscriptions not before the previous is finish processed in plc
Expand Down
4 changes: 2 additions & 2 deletions docs/de/admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ Dieses Projekt hat keine Verbindung mit der Firma Beckhoff

3. Bei TwinCat 2 muss in der Steuerung noch eine Struktur angelegt werden. Die Struktur danach zu einer globalen Variablentabelle hinzufügen. Hier können dann alle benötigten Variablen angelegt werden. Der Datenaustausch wird dann von ADS und dem Adapter selbstständig ausgeführt.

##### Derzeit unterstützte Datentypen: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, STRING(80)
##### Derzeit unterstützte Datentypen: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT, STRING

OPTIONAL: Es kann eine Variable direkt in der Variablentabelle ohne Verschachtelung mit einem exakten Namen angelegt werden -> ioBrokerResync (Groß-/Kleinschreibung und Datentyp ist egal) -> Jedes mal wenn sich dieser Wert ändert wird die Variablentabelle im ioBroker neu eingelesen.

3. Bei TwinCat 3 muss in der Steuerung noch eine globale Variablentabelle angelegt werden. Hier können dann alle benötigten Variablen angelegt werden. Der Datenaustausch wird dann von ADS und dem Adapter selbstständig ausgeführt.

##### Derzeit unterstützte Datentypen: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, STRING(80)
##### Derzeit unterstützte Datentypen: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT, STRING

OPTIONAL: Es kann eine Variable direkt in der Variablentabelle ohne Verschachtelung mit einem exakten Namen angelegt werden -> ioBrokerResync (Groß-/Kleinschreibung und Datentyp ist egal) -> Jedes mal wenn sich dieser Wert ändert wird die Variablentabelle im ioBroker neu eingelesen.

Expand Down
4 changes: 2 additions & 2 deletions docs/en/admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ This Project is not affilate to Beckhoff in any way

3. On TwinCat 2 Create a Struct and fill in your needed Symbols. Then add this Struct to a GlobalVariableTable.

##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, STRING(80)
##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT, STRING

OPTIONAL: You can create a Variable in root of Struct with the exact name -> ioBrokerResync (Not Casesensitiv and not matter which Type) -> Every time this Variable changes his value the Table get resynced in ioBroker.

4. On TwinCat 3 Create a GlobalVariableTable and fill in your needed Symbols.

##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, STRING(80)
##### Currently Supported Types: BOOL, BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL, LREAL, TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT, STRING

OPTIONAL: You can create a Variable in root of Variable Table with the exact name -> ioBrokerResync (Not Casesensitiv and not matter which Type) -> Every time this Variable changes his value the Table get resynced in ioBroker.

Expand Down
14 changes: 13 additions & 1 deletion io-package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"common": {
"name": "beckhoff",
"version": "1.5.0",
"version": "1.5.1",
"news": {
"1.0.4": {
"en": "Increase depth of LOG Details, Update Dependency Versions",
Expand Down Expand Up @@ -146,6 +146,18 @@
"es": "Procese el siguiente estado en la lista cuando registre suscripciones no antes de que termine el procesamiento anterior en plc",
"pl": "Przetwarzaj następny stan na liście, gdy zarejestruj subskrypcje nie przed zakończeniem poprzedniego przetwarzania w PLC",
"zh-cn": "当注册订阅不在 plc 中前一个完成处理之前处理列表中的下一个状态"
},
"1.5.1": {
"en": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT support and support for strings with all char length added",
"de": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT-Unterstützung und Unterstützung für Zeichenfolgen mit hinzugefügter Zeichenlänge",
"ru": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, поддержка DT и поддержка строк с добавленной длиной всех символов",
"pt": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, suporte DT e suporte para strings com todos os comprimentos de caracteres adicionados",
"nl": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT-ondersteuning en ondersteuning voor strings met alle tekenlengtes toegevoegd",
"fr": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, prise en charge de DT et prise en charge des chaînes avec toute la longueur de caractères ajoutée",
"it": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, supporto DT e supporto per stringhe con tutta la lunghezza del carattere aggiunta",
"es": "TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, compatibilidad con DT y compatibilidad con cadenas con todas las longitudes de caracteres añadidas",
"pl": "Obsługa TIME, TIME_OF_DAY, TOD, DATE, DATE_AND_TIME, DT i obsługa ciągów znaków z dodaną długością znaków",
"zh-cn": "TIME、TIME_OF_DAY、TOD、DATE、DATE_AND_TIME、DT 支持并支持添加了所有字符长度的字符串"
}
},
"title": "Beckhoff TwinCat ADS",
Expand Down
11 changes: 7 additions & 4 deletions lib/createObjectsAndHandles.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ module.exports = (adsC, adapter) => {
}

if (item.bytelength.name === 'STRING') {
symbolName = `${symbolName} [STRING(80)]`;
symbolName = `${symbolName} [STRING(${item.bytelength.length - 1})]`;
} else {
symbolName = `${symbolName} [${item.bytelength.name}]`;
}
Expand All @@ -143,12 +143,15 @@ module.exports = (adsC, adapter) => {
type = 'boolean';
def = false;
role = 'switch';
}

if (item.bytelength.name === 'STRING') {
} else if (item.bytelength.name === 'STRING') {
type = 'string';
def = '';
role = 'text';
} else if (['TIME', 'TIME_OF_DAY', 'TOD', 'DATE', 'DATE_AND_TIME', 'DT'].includes(item.bytelength.name)) {
item.bytelength.useLocalTimezone = false;
type = 'string';
def = '';
role = 'date';
}

let statename = '';
Expand Down
34 changes: 27 additions & 7 deletions lib/plcVarSyncronizing.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,26 @@ module.exports = function plcVarSync(adsC, adapter, emitter) {
* @returns {array} SymbolList for creating States in ioBroker and subscibe the Handles
*/
function createSymbolObjectList(datatypList, symbolList, datatypeIndex, prefix) {
const knownDatatypes = ['BOOL', 'BYTE', 'WORD', 'DWORD', 'SINT', 'USINT', 'INT', 'UINT', 'DINT', 'UDINT', 'REAL', 'LREAL', 'STRING(80)'];
const knownDatatypes = [
'BOOL',
'BYTE',
'WORD',
'DWORD',
'SINT',
'USINT',
'INT',
'UINT',
'DINT',
'UDINT',
'REAL',
'LREAL',
'TIME',
'TIME_OF_DAY',
'TOD',
'DATE',
'DATE_AND_TIME',
'DT',
];

const tempObject = {
symname: '',
Expand All @@ -90,16 +109,17 @@ function createSymbolObjectList(datatypList, symbolList, datatypeIndex, prefix)
}

// Is the Datatype a known basic Datatype then Create an Push Datapointobject to OutputArray
if (knownDatatypes.includes(symbolList[i].type)) {
if (symbolList[i].type.match('^STRING\\(\\d+\\)$') || knownDatatypes.includes(symbolList[i].type)) {
tempObject.symname = symbolList[i].name;

if (symbolList[i].type === 'STRING(80)') {
tempObject.bytelength = ads.STRING;
if (symbolList[i].type.match('^STRING\\(\\d+\\)$')) {
tempObject.bytelength = ads.string(symbolList[i].size - 1);
} else {
tempObject.bytelength = ads[symbolList[i].type];
}

symbolObjectList.push(JSON.parse(JSON.stringify(tempObject)));

continue;
}

Expand Down Expand Up @@ -142,11 +162,11 @@ function createSymbolObjectList(datatypList, symbolList, datatypeIndex, prefix)
}

// When we found here some basic Datatypes -> Adding to Datapointarray with complete Path
if (knownDatatypes.includes(datatyps[i].type)) {
if (datatyps[i].type.match('^STRING\\(\\d+\\)$') || knownDatatypes.includes(datatyps[i].type)) {
tempObject.symname = `${prefix}${datatyps[i].name}`;

if (datatyps[i].type === 'STRING(80)') {
tempObject.bytelength = ads.STRING;
if (datatyps[i].type.match('^STRING\\(\\d+\\)$')) {
tempObject.bytelength = ads.string(datatyps[i].size - 1);
} else {
tempObject.bytelength = ads[datatyps[i].type];
}
Expand Down
49 changes: 39 additions & 10 deletions lib/tpyParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,26 @@ module.exports = (adapter, emitter) => {
* @returns {array} SymbolList for creating States in ioBroker and subscibe the Handles
*/
function createSymbolObjectList(datatyps, symbols, datatypeIndex, prefix) {
const knownDatatypes = ['BOOL', 'BYTE', 'WORD', 'DWORD', 'SINT', 'USINT', 'INT', 'UINT', 'DINT', 'UDINT', 'REAL', 'LREAL', 'STRING(80)'];
const knownDatatypes = [
'BOOL',
'BYTE',
'WORD',
'DWORD',
'SINT',
'USINT',
'INT',
'UINT',
'DINT',
'UDINT',
'REAL',
'LREAL',
'TIME',
'TIME_OF_DAY',
'TOD',
'DATE',
'DATE_AND_TIME',
'DT',
];

const tempObject = {
symname: '',
Expand Down Expand Up @@ -109,15 +128,16 @@ function createSymbolObjectList(datatyps, symbols, datatypeIndex, prefix) {
}

// Is the Datatype a String then Create an Push Datapointobject to OutputArray
if (knownDatatypes.includes(symbols[i].Type[0]._)) {
if (symbols[i].Type[0]._.match('^STRING\\(\\d+\\)$')) {
if (symbols[i].Name[0]._) {
tempObject.symname = symbols[i].Name[0]._;
} else {
[tempObject.symname] = symbols[i].Name;
}

if (symbols[i].Type[0]._ === 'STRING(80)') {
tempObject.bytelength = ads.STRING;
const check = symbols[i].Type[0]._.match('^STRING\\((\\d+)\\)$');
if (check) {
tempObject.bytelength = ads.string(parseInt(check[1], 10));
symbolObjectList.push(JSON.parse(JSON.stringify(tempObject)));
continue;
}
Expand Down Expand Up @@ -166,20 +186,29 @@ function createSymbolObjectList(datatyps, symbols, datatypeIndex, prefix) {
for (let i = 0; i < datatyp.length; i += 1) {
// When we found here some basic Datatypes -> Adding to Datapointarray with complete Path
if (knownDatatypes.includes(datatyp[i].Type[0])) {
tempObject.symname = `${prefix}${datatyp[i].Name[0]}`;
if (datatyp[i].Name[0]._) {
tempObject.symname = `${prefix}${datatyp[i].Name[0]._}`;
} else {
tempObject.symname = `${prefix}${datatyp[i].Name[0]}`;
}

tempObject.bytelength = ads[datatyp[i].Type[0]];

symbolObjectList.push(JSON.parse(JSON.stringify(tempObject)));
continue;
}

// When we found here some String(80) -> Adding to Datapointarray with complete Path
if (knownDatatypes.includes(datatyp[i].Type[0]._)) {
tempObject.symname = `${prefix}${datatyp[i].Name[0]}`;
// When we found here some String -> Adding to Datapointarray with complete Path
if (datatyp[i].Type[0]._.match('^STRING\\(\\d+\\)$') || knownDatatypes.includes(datatyp[i].Type[0]._)) {
if (datatyp[i].Name[0]._) {
tempObject.symname = `${prefix}${datatyp[i].Name[0]._}`;
} else {
tempObject.symname = `${prefix}${datatyp[i].Name[0]}`;
}

if (datatyp[i].Type[0]._ === 'STRING(80)') {
tempObject.bytelength = ads.STRING;
const check = datatyp[i].Type[0]._.match('^STRING\\((\\d+)\\)$');
if (check) {
tempObject.bytelength = ads.string(parseInt(check[1], 10));
symbolObjectList.push(JSON.parse(JSON.stringify(tempObject)));
continue;
}
Expand Down
13 changes: 10 additions & 3 deletions lib/workerAdapterToPlc.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,16 @@ module.exports = (adsC, adapter, emitter, state, id) => {
value: state.val,
};

if (obj.native.bytelength.name === 'STRING' && state.val.length > 80) {
adapter.log.warn(`WorkerAdapterToPLC received a String that is longer than 80 Chars: ${symname} -> Cut to 80 Chars`);
plcHandle.value = state.val.substr(0, 80);
if (obj.native.bytelength.name === 'STRING' && state.val.length > obj.native.bytelength.length - 1) {
adapter.log.warn(
`WorkerAdapterToPLC received a String that is longer than ${obj.native.bytelength.length - 1} Chars: ${symname} -> Cut to ${
obj.native.bytelength.length - 1
} Chars`
);
plcHandle.value = state.val.substr(0, obj.native.bytelength.length - 1);
} else if (['TIME', 'TIME_OF_DAY', 'TOD', 'DATE', 'DATE_AND_TIME', 'DT'].includes(obj.native.bytelength.name)) {
// iobroker wants the date and time to be of type Number. The PLC implementation would like a date
plcHandle.value = new Date(plcHandle.value);
}

adsC.write(plcHandle, error => {
Expand Down
6 changes: 6 additions & 0 deletions lib/workerPlcToAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ module.exports = (adsC, adapter, emitter) => {
return;
}

if (handle.value instanceof Date) {
// iobroker wants the date and time to be of type String or Number. The PLC implementation would like a date
// we make String, with Iso String everything is converted, so we remove iso characters
handle.value = handle.value.toISOString().replace('T', ' ').replace('Z', '');
}

let statename = '';

// TC2 have a Point on Globals TC3 don´t have
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "iobroker.beckhoff",
"description": "ioBroker Beckoff Adapter to communicate with a Beckhoff PLC",
"version": "1.5.0",
"version": "1.5.1",
"private": false,
"license": "MIT",
"keywords": [
Expand Down

0 comments on commit 1ed8f83

Please sign in to comment.