-
Notifications
You must be signed in to change notification settings - Fork 13
Feature-Request: Allow to set the c104.type of a point #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hello Georg, Thank you for your feedback. Currently, it was a design choice to have different information object addresses (IOAs) for distinct types. This approach helps avoid unexpected payload formats and minimizes repeated type checking, ensuring that each data type has its own distinct identity in the communication flow. One potential solution would be to implement another abstraction layer in your code that internally manages two separate points (one for each type) but exposes them as a single logical entity externally. Alternatively, you could consider sending a timestamp with a known "unset" state (such as 0) when you want the client to ignore it. However, this approach would require you to have control over the client as well, to ensure the client-side logic disregards the zero timestamp and retains the previous valid one. May I ask, what specific challenges are you facing with sending a timestamp too frequently? Is it that the correct timestamp value isn't available at the time of transmission, or is there another reason for preferring to omit it in certain scenarios? Looking forward to your feedback. |
Hello Martin, thanks a lot for your help and solution proposals. Fortunately we now agreed in our integration-prototype not mix message-types for already defined datapoints, thus following your design decision. Switching the datatype of an already created entity would also allow that you can witch from value-report to step-command. Answering your question: We also have been working on another topic, setting the daylight-saving-time bit for messages. This approach is not very generic and must be adapted for every message type. Would great to have your feedback on this. Shall I open another thread for this? (Hint: We know that using the SU-BIT in iec104 according to the Din-Norm is not recommended). Thanks in advance |
Hello Georg, Regarding the timestamps, we can continue the discussion in this thread; next time, please feel free to open a parallel issue. I saw your pull request, but you closed it again. Generally, a contributor license agreement would be necessary for a pull request of this magnitude. The timestamp in the protocol also comes with an invalid flag, which can be used for the previously mentioned marking of invalid timestamps instead of a defined "unset" state. There is the possibility of creating a wrapper class (i.e., However, the question remains where the state of DST is stored. In your PR, the state was assigned to the server. But does it really make sense for state to vary per server/client instance of a running process? Otherwise, I would tend to consider a static class property as a global configuration that is valid for all servers and clients in the running Python process (c104.DateTime.summerTime = True). Best |
In general, this approach could be used to flag all timestamps implicitly added by this module as substituted. For example, if I change the value of a point that has a type with an associated timestamp by using |
The requested feature has been implemented. I am currently working on an example that demonstrates its use for internal clock synchronization via the clock sync command. Since this implementation introduces breaking changes, I was unable to include it in the latest release—apologies for the slow progress. If you'd like, you can verify the new feature by installing it from the source branch. pip install git+https://github.com/Fraunhofer-FIT-DIEN/iec104-python.git@features/datetime This example showcases different options a server could use to take advantage of the datetime feature: import c104
import time
from datetime import datetime, timezone, timedelta
def main():
# server and station preparation
server = c104.Server()
station = server.add_station(common_address=47)
station.auto_time_substituted = False
point = station.add_point(io_address=11, type=c104.Type.M_ME_TD_1)
# start
server.start()
while not server.has_active_connections:
print("Waiting for connection")
time.sleep(1)
time.sleep(1)
print("transmit point 0 (none)")
dt0 = c104.DateTime(datetime.now(timezone.utc))
dt0.daylight_saving_time = False
dt0.invalid = True
dt0.substituted = True
point.info = c104.NormalizedInfo(
c104.NormalizedFloat(0.34),
c104.Quality(),
dt0
)
point.transmit(c104.Cot.SPONTANEOUS)
time.sleep(1)
print("transmit point 1 (Offset)")
dt1 = c104.DateTime(datetime.now(timezone(timedelta(seconds=3600))))
dt1.daylight_saving_time = False
print(dt1.value.isoformat())
point.info = c104.NormalizedInfo(
c104.NormalizedFloat(-0.34),
c104.Quality(),
dt1
)
point.transmit(c104.Cot.SPONTANEOUS)
time.sleep(1)
print("transmit point 2 (DST)")
dt2 = c104.DateTime(datetime.now(timezone.utc))
dt2.daylight_saving_time = True
print(dt2.value.isoformat())
point.info = c104.NormalizedInfo(
c104.NormalizedFloat(0.35),
c104.Quality(),
dt2
)
point.transmit(c104.Cot.SPONTANEOUS)
time.sleep(1)
print("transmit point 3 (Station offset)")
station.timezone_offset = 14400
station.daylight_saving_time = True
dt3 = c104.DateTime(datetime.now(timezone(timedelta(seconds=14400))))
dt3.daylight_saving_time = False
print(dt3.value.isoformat())
point.info = c104.NormalizedInfo(
c104.NormalizedFloat(-0.35),
c104.Quality(),
dt3
)
point.transmit(c104.Cot.SPONTANEOUS)
time.sleep(1)
print("transmit point 4 (Station offset+DST)")
station.timezone_offset = 14400
dt4 = c104.DateTime(datetime.now(timezone(timedelta(seconds=14400))))
dt4.daylight_saving_time = True
print(dt4.value.isoformat())
point.info = c104.NormalizedInfo(
c104.NormalizedFloat(0.36),
c104.Quality(),
dt4
)
point.transmit(c104.Cot.SPONTANEOUS)
time.sleep(1)
print("transmit point 5 (auto substituted)")
point.value = c104.NormalizedFloat(0.0)
point.transmit(c104.Cot.SPONTANEOUS)
server.stop()
if __name__ == "__main__":
print()
print("START simple server")
print()
main() |
One additional thought: For version 3.0, we are considering using the same point for messages with and without a timestamp. As per the standard, COT periodic messages will use messages without a timestamp, while all other cases will include a timestamp. |
Hello,
we have a scenario where we might want to transmit a point in two different variations.
So basically the underlying data-type shall not change.
Depending on the scenario (Interrogation, Spontaneous) we would like to send the value either with or without timestamp.
Unfortunately there is no setter for the type of a point.
Is it possible to allow setting the type of an already changes point?
Thanks a lot in advance
Georg
The text was updated successfully, but these errors were encountered: