Skip to content

Commit

Permalink
refactor(times): Refactoring of the was PlcValues are handled for TIM…
Browse files Browse the repository at this point in the history
…E, DATE, TIME_OF_DAY and DATE_TIME types.

- Actually made serializing of temporal values possible. Till now we simply called "getValue" which really could never have worked with temporal types. Now everything should be way more explicit and actually working.

- Fixed invalid type definitions for long temporal types in ADS
- Fixed too small types for long temporal types in PLC4X (Proxy Protocol)
  • Loading branch information
chrisdutz committed Nov 25, 2022
1 parent e73b569 commit 76bcb48
Show file tree
Hide file tree
Showing 31 changed files with 346 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,15 @@ func ${type.name}SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer, value a
<#assign simpleField = field.asSimpleField().orElseThrow()>

// Simple Field (${simpleField.name})
<#if (case.name == "TIME") || (case.name == "LTIME") || (case.name == "DATE") || (case.name == "LDATE") || (case.name == "TIME_OF_DAY") || (case.name == "LTIME_OF_DAY") || (case.name == "DATE_AND_TIME") || (case.name == "LDATE_AND_TIME")>
if _err := ${helper.getWriteBufferWriteMethodCall(simpleField.name, simpleField.type.asSimpleTypeReference().orElseThrow(), "value.(values.Plc${case.name}).Get${simpleField.name?cap_first}()", simpleField)}; _err != nil {
return errors.Wrap(_err, "Error serializing '${simpleField.name}' field")<@emitImport import="github.com/pkg/errors" />
}
<#else>
if _err := <#if simpleField.type.isSimpleTypeReference()>${helper.getWriteBufferWriteMethodCall(simpleField.name, simpleField.type.asSimpleTypeReference().orElseThrow(), "value.Get" + helper.getLanguageTypeNameForTypeReference(simpleField.type)?cap_first + "()", simpleField)}<#else>${simpleField.type.asComplexTypeReference().orElseThrow().name}Serialize(io, <#if simpleField.type.asComplexTypeReference().orElseThrow().params.isPresent()>, <#list simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index))}) (${helper.toParseExpression(simpleField, helper.getArgumentType(simpleField.type, parserArgument?index), parserArgument, parserArguments)})<#sep>, </#sep></#list></#if>)</#if>; _err != nil {
return errors.Wrap(_err, "Error serializing '${simpleField.name}' field")<@emitImport import="github.com/pkg/errors" />
}
</#if>
<#break>
</#switch>
</#list>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,54 +405,77 @@ public class ${type.name} {
}
</#if>

<#if case.name == "BOOL">
<#if case.name == "BOOL">
while (writeBuffer.getPos() < writeBuffer.getData().length) {
writeBuffer.writeBit(false);
}
</#if>
<#break>
</#if>
<#break>
<#case "const">
<#assign constField=field.asConstField().orElseThrow()>
// Const Field (${constField.name})
${helper.getWriteBufferWriteMethodCall(constField.type.asSimpleTypeReference().orElseThrow(), constField.referenceValue, constField)};
<#break>
<#break>
<#case "enum">
<#assign enumField=field.asEnumField().orElseThrow()>
// Enum field (${enumField.name})
${helper.getLanguageTypeNameForField(field)} ${enumField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${enumField.name?cap_first}();
${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(field.asTypedField().orElseThrow().type), "(" + enumField.name + ".getValue())", enumField)};
<#break>
<#break>
<#case "manual">
<#assign manualField=field.asManualField().orElseThrow()>
// Manual Field (${manualField.name})
${helper.toSerializationExpression(manualField, manualField.type, manualField.serializeExpression, type.parserArguments.orElse(null))};
<#break>
<#break>
<#case "reserved">
<#assign reservedField=field.asReservedField().orElseThrow()>
// Reserved Field
${helper.getWriteBufferWriteMethodCall(reservedField.type.asSimpleTypeReference().orElseThrow(), helper.getReservedValue(reservedField), reservedField)};
<#break>
<#break>
<#case "simple">
<#assign simpleField=field.asSimpleField().orElseThrow()>
// Simple Field (${simpleField.name})
<#if case.name == "Struct">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.getStruct().get("${simpleField.name}").get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#else>
<#if simpleField.name == "value">
<#elseif simpleField.name == "value">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "secondsSinceEpoch">
<#elseif simpleField.name == "secondsSinceEpoch">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "daysSinceEpoch">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "daysSinceSiemensEpoch">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "year">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "month">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "day">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "dayOfWeek">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "hour">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "minutes">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "seconds">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "milliseconds">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "millisecondsSinceMidnight">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "nanoseconds">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "nanosecondsSinceMidnight">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#elseif simpleField.name == "nanosecondsSinceEpoch">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#else>
<#-- Just for now -->
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = ${helper.getNullValueForTypeReference(simpleField.type)};
</#if>
</#if>
<#if simpleField.type.isSimpleTypeReference()>
${helper.getWriteBufferWriteMethodCall(simpleField.type.asSimpleTypeReference().orElseThrow(), "(" + simpleField.name + ")", simpleField)};
<#else>
${simpleField.type.asComplexTypeReference().orElseThrow().name}IO.staticSerialize(writeBuffer, ${simpleField.name});
</#if>
<#break>
<#break>
</#switch>
</#list>
}<#sep> else </#sep></#list>
Expand Down
16 changes: 8 additions & 8 deletions plc4c/generated-sources/plc4x/src/plc4x_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ plc4c_return_code plc4c_plc4x_read_write_plc4x_value_parse(plc4c_spi_read_buffer
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_LDATE) { /* LDATE */

// Simple Field (nanosecondsSinceEpoch)
uint32_t nanosecondsSinceEpoch = 0;
_res = plc4c_spi_read_unsigned_int(readBuffer, 32, (uint32_t*) &nanosecondsSinceEpoch);
uint64_t nanosecondsSinceEpoch = 0;
_res = plc4c_spi_read_unsigned_long(readBuffer, 64, (uint64_t*) &nanosecondsSinceEpoch);
if(_res != OK) {
return _res;
}
Expand Down Expand Up @@ -315,8 +315,8 @@ plc4c_return_code plc4c_plc4x_read_write_plc4x_value_parse(plc4c_spi_read_buffer
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_LDATE_AND_TIME) { /* LDATE_AND_TIME */

// Simple Field (nanosecondsSinceEpoch)
uint32_t nanosecondsSinceEpoch = 0;
_res = plc4c_spi_read_unsigned_int(readBuffer, 32, (uint32_t*) &nanosecondsSinceEpoch);
uint64_t nanosecondsSinceEpoch = 0;
_res = plc4c_spi_read_unsigned_long(readBuffer, 64, (uint64_t*) &nanosecondsSinceEpoch);
if(_res != OK) {
return _res;
}
Expand Down Expand Up @@ -476,7 +476,7 @@ plc4c_return_code plc4c_plc4x_read_write_plc4x_value_serialize(plc4c_spi_write_b
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_LDATE) { /* LDATE */

// Simple field (nanosecondsSinceEpoch)
_res = plc4c_spi_write_unsigned_int(writeBuffer, 32, (*data_item)->data.ldate_value);
_res = plc4c_spi_write_unsigned_long(writeBuffer, 64, (*data_item)->data.ldate_value);
if(_res != OK) {
return _res;
}
Expand Down Expand Up @@ -504,7 +504,7 @@ plc4c_return_code plc4c_plc4x_read_write_plc4x_value_serialize(plc4c_spi_write_b
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_LDATE_AND_TIME) { /* LDATE_AND_TIME */

// Simple field (nanosecondsSinceEpoch)
_res = plc4c_spi_write_unsigned_int(writeBuffer, 32, (*data_item)->data.ldate_and_time_value);
_res = plc4c_spi_write_unsigned_long(writeBuffer, 64, (*data_item)->data.ldate_and_time_value);
if(_res != OK) {
return _res;
}
Expand Down Expand Up @@ -605,7 +605,7 @@ uint16_t plc4c_plc4x_read_write_plc4x_value_length_in_bits(plc4c_data* data_item
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_LDATE) { /* LDATE */

// Simple field (nanosecondsSinceEpoch)
lengthInBits += 32;
lengthInBits += 64;
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_TIME_OF_DAY) { /* TIME_OF_DAY */

// Simple field (millisecondsSinceMidnight)
Expand All @@ -621,7 +621,7 @@ uint16_t plc4c_plc4x_read_write_plc4x_value_length_in_bits(plc4c_data* data_item
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_LDATE_AND_TIME) { /* LDATE_AND_TIME */

// Simple field (nanosecondsSinceEpoch)
lengthInBits += 32;
lengthInBits += 64;
} else if(valueType == plc4c_plc4x_read_write_plc4x_value_type_Struct) { /* Struct */
}
return lengthInBits;
Expand Down
24 changes: 12 additions & 12 deletions plc4c/generated-sources/s7/src/data_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,25 +284,25 @@ plc4c_return_code plc4c_s7_read_write_data_item_parse(plc4c_spi_read_buffer* rea

} else if(strcmp(dataProtocolId, "IEC61131_TIME_OF_DAY") == 0) { /* TIME_OF_DAY */

// Simple Field (milliseconds)
uint32_t milliseconds = 0;
_res = plc4c_spi_read_unsigned_int(readBuffer, 32, (uint32_t*) &milliseconds);
// Simple Field (millisecondsSinceMidnight)
uint32_t millisecondsSinceMidnight = 0;
_res = plc4c_spi_read_unsigned_int(readBuffer, 32, (uint32_t*) &millisecondsSinceMidnight);
if(_res != OK) {
return _res;
}

*data_item = plc4c_data_create_time_of_day_data(milliseconds);
*data_item = plc4c_data_create_time_of_day_data(millisecondsSinceMidnight);

} else if(strcmp(dataProtocolId, "IEC61131_LTIME_OF_DAY") == 0) { /* LTIME_OF_DAY */

// Simple Field (nanoseconds)
uint64_t nanoseconds = 0;
_res = plc4c_spi_read_unsigned_long(readBuffer, 64, (uint64_t*) &nanoseconds);
// Simple Field (nanosecondsSinceMidnight)
uint64_t nanosecondsSinceMidnight = 0;
_res = plc4c_spi_read_unsigned_long(readBuffer, 64, (uint64_t*) &nanosecondsSinceMidnight);
if(_res != OK) {
return _res;
}

*data_item = plc4c_data_create_ltime_of_day_data(nanoseconds);
*data_item = plc4c_data_create_ltime_of_day_data(nanosecondsSinceMidnight);

} else if(strcmp(dataProtocolId, "IEC61131_DATE_AND_TIME") == 0) { /* DATE_AND_TIME */

Expand Down Expand Up @@ -542,14 +542,14 @@ plc4c_return_code plc4c_s7_read_write_data_item_serialize(plc4c_spi_write_buffer
}
} else if(strcmp(dataProtocolId, "IEC61131_TIME_OF_DAY") == 0) { /* TIME_OF_DAY */

// Simple field (milliseconds)
// Simple field (millisecondsSinceMidnight)
_res = plc4c_spi_write_unsigned_int(writeBuffer, 32, (*data_item)->data.time_of_day_value);
if(_res != OK) {
return _res;
}
} else if(strcmp(dataProtocolId, "IEC61131_LTIME_OF_DAY") == 0) { /* LTIME_OF_DAY */

// Simple field (nanoseconds)
// Simple field (nanosecondsSinceMidnight)
_res = plc4c_spi_write_unsigned_long(writeBuffer, 64, (*data_item)->data.ltime_of_day_value);
if(_res != OK) {
return _res;
Expand Down Expand Up @@ -712,11 +712,11 @@ uint16_t plc4c_s7_read_write_data_item_length_in_bits(plc4c_data* data_item, cha
lengthInBits += 16;
} else if(strcmp(dataProtocolId, "IEC61131_TIME_OF_DAY") == 0) { /* TIME_OF_DAY */

// Simple field (milliseconds)
// Simple field (millisecondsSinceMidnight)
lengthInBits += 32;
} else if(strcmp(dataProtocolId, "IEC61131_LTIME_OF_DAY") == 0) { /* LTIME_OF_DAY */

// Simple field (nanoseconds)
// Simple field (nanosecondsSinceMidnight)
lengthInBits += 64;
} else if(strcmp(dataProtocolId, "IEC61131_DATE_AND_TIME") == 0) { /* DATE_AND_TIME */

Expand Down
31 changes: 19 additions & 12 deletions plc4go/examples/ads/write/Write.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package main

import (
"time"

plc4go "github.com/apache/plc4x/plc4go/pkg/api"
"github.com/apache/plc4x/plc4go/pkg/api/drivers"
values2 "github.com/apache/plc4x/plc4go/pkg/api/values"
Expand All @@ -33,6 +35,12 @@ func main() {
connectionChan := driverManager.GetConnection("ads:tcp://192.168.23.20?sourceAmsNetId=192.168.23.200.1.1&sourceAmsPort=65534&targetAmsNetId=192.168.23.20.1.1&targetAmsPort=851")
connection := <-connectionChan

duration, _ := time.ParseDuration("1.234S")
lduration, _ := time.ParseDuration("24015H23M12.034002044S")
date, _ := time.Parse("2014-11-12", "1978-03-28")
timeOfDay, _ := time.Parse("11:45:26.371Z", "15:36:30.123")
dateAndTime, _ := time.Parse("2014-11-12T11:45:26.371Z", "1996-05-06T15:36:30")

// Prepare the data structure for a custom type.
children := map[string]values2.PlcValue{}
children["hurz_BOOL"] = values.NewPlcBOOL(true)
Expand All @@ -52,12 +60,11 @@ func main() {
children["hurz_LREAL"] = values.NewPlcLREAL(14.0)
children["hurz_STRING"] = values.NewPlcSTRING("hurz")
children["hurz_WSTRING"] = values.NewPlcWSTRING("wolf")
//children["hurz_TIME"] = values.NewPlcTIME(Duration.parse("PT1.234S"))
//children["hurz_LTIME"] = values.NewPlcLTIME(Duration.parse("PT24015H23M12.034002044S"))
//children["hurz_DATE"] = values.NewPlcDATE(LocalDate.parse("1978-03-28"))
//children["hurz_TIME_OF_DAY"] = values.NewPlcTIME_OF_DAY(LocalTime.parse("15:36:30.123"))
//children["hurz_DATE_AND_TIME"] = values.NewPlcDATE_AND_TIME(LocalDateTime.parse("1996-05-06T15:36:30"))

children["hurz_TIME"] = values.NewPlcTIME(duration)
children["hurz_LTIME"] = values.NewPlcLTIME(lduration)
children["hurz_DATE"] = values.NewPlcDATE(date)
children["hurz_TIME_OF_DAY"] = values.NewPlcTIME_OF_DAY(timeOfDay)
children["hurz_DATE_AND_TIME"] = values.NewPlcDATE_AND_TIME(dateAndTime)
writeRequest, err := connection.GetConnection().WriteRequestBuilder().
AddTagAddress("value-bool", "MAIN.hurz_BOOL", values.NewPlcBOOL(true)). // 1
AddTagAddress("value-byte", "MAIN.hurz_BYTE", values.NewPlcBYTE(42)). // 1
Expand All @@ -76,12 +83,12 @@ func main() {
AddTagAddress("value-lreal", "MAIN.hurz_LREAL", values.NewPlcLREAL(2.71828182846)). // 8
AddTagAddress("value-string", "MAIN.hurz_STRING", values.NewPlcSTRING("hurz")). // 4
AddTagAddress("value-wstring", "MAIN.hurz_WSTRING", values.NewPlcWSTRING("wolf")). // 8
/*AddTagAddress("value-time", "MAIN.hurz_TIME")).
AddTagAddress("value-ltime", "MAIN.hurz_LTIME")).
AddTagAddress("value.date", "MAIN.hurz_DATE")).
AddTagAddress("value-time-of-day", "MAIN.hurz_TIME_OF_DAY")).
AddTagAddress("value-date-and-time", "MAIN.hurz_DATE_AND_TIME")).*/
AddTagAddress("value-struct", "MAIN.hurz_Struct", values.NewPlcStruct(children)).
AddTagAddress("value-time", "MAIN.hurz_TIME", values.NewPlcTIME(duration)).
AddTagAddress("value-ltime", "MAIN.hurz_LTIME", values.NewPlcLTIME(lduration)).
AddTagAddress("value.date", "MAIN.hurz_DATE", values.NewPlcDATE(date)).
AddTagAddress("value-time-of-day", "MAIN.hurz_TIME_OF_DAY", values.NewPlcTIME_OF_DAY(timeOfDay)).
AddTagAddress("value-date-and-time", "MAIN.hurz_DATE_AND_TIME", values.NewPlcDATE_AND_TIME(dateAndTime)).
//AddTagAddress("value-struct", "MAIN.hurz_Struct", values.NewPlcStruct(children)).
Build()
if err != nil {
panic(err)
Expand Down
Loading

0 comments on commit 76bcb48

Please sign in to comment.