Skip to content
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

Support more message (all FRBC related) #5

Merged
merged 8 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/spec/reports/
/tmp/
spec/examples.txt
.idea
3 changes: 3 additions & 0 deletions .rubocop_disabled.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ Style/ClassAndModuleChildren: # Decide what we want

Style/Documentation: # No, just no
Enabled: false

Naming/MethodParameterName: # single letter params are fine
Enabled: false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MinNameLength: 1 werkt ook, dan kan de cop verder aanblijven.

17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
# S2

TODO: Delete this and the text below, and describe your gem
## Requirements

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/s2`. To experiment with that code, run `bin/console` for an interactive prompt.
```bash
brew install quicktype
```

## Code generation

To generate boilerplate code for the S2 library, run the following command:
```bash
bin/gen-types
```

Move these to the `lib/s2` directory and adjust them according to the existing examples.

```bash

## Installation

Expand Down
13 changes: 13 additions & 0 deletions lib/s2-ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@
require "active_support/all"

require_relative "s2/version"

require_relative "s2/messages/types"
require_relative "s2/schemas/number_range"

require_relative "s2/messages/frbc_actuator_status"
require_relative "s2/messages/frbc_fill_level_target_profile"
require_relative "s2/messages/frbc_instruction"
require_relative "s2/messages/frbc_leakage_behaviour"
require_relative "s2/messages/frbc_storage_status"
require_relative "s2/messages/frbc_system_description"
require_relative "s2/messages/frbc_timer_status"
require_relative "s2/messages/frbc_usage_forecast"
require_relative "s2/messages/handshake"
require_relative "s2/messages/handshake_response"
require_relative "s2/messages/reception_status"
require_relative "s2/messages/resource_manager_details"

require_relative "s2/message_factory"
require_relative "s2/message_handler"
require_relative "s2/message_handler_callbacks"
Expand Down
68 changes: 68 additions & 0 deletions lib/s2/messages/frbc_actuator_status.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
module S2
module Messages
module MessageType
FRBCActuatorStatus = "FRBC.ActuatorStatus"
end

class FrbcActuatorStatus < Dry::Struct

# ID of the FRBC.OperationMode that is presently active.
attribute :active_operation_mode_id, Types::String

# ID of the actuator this messages refers to
attribute :actuator_id, Types::String

# ID of this message
attribute :message_id, Types::String

attribute :message_type, Types::MessageType

# The number indicates the factor with which the FRBC.OperationMode is configured. The
# factor should be greater than or equal than 0 and less or equal to 1.
attribute :operation_mode_factor, Types::Double

# ID of the FRBC.OperationMode that was active before the present one. This value shall
# always be provided, unless the active FRBC.OperationMode is the first FRBC.OperationMode
# the Resource Manager is aware of.
attribute :previous_operation_mode_id, Types::String.optional

# Time at which the transition from the previous FRBC.OperationMode to the active
# FRBC.OperationMode was initiated. This value shall always be provided, unless the active
# FRBC.OperationMode is the first FRBC.OperationMode the Resource Manager is aware of.
attribute :transition_timestamp, Types::String.optional

def self.from_dynamic!(d)
d = Types::Hash[d]
new(
active_operation_mode_id: d.fetch("active_operation_mode_id"),
actuator_id: d.fetch("actuator_id"),
message_id: d.fetch("message_id"),
message_type: d.fetch("message_type"),
operation_mode_factor: d.fetch("operation_mode_factor"),
previous_operation_mode_id: d["previous_operation_mode_id"],
transition_timestamp: d["transition_timestamp"],
)
end

def self.from_json!(json)
from_dynamic!(JSON.parse(json))
end

def to_dynamic
{
"active_operation_mode_id" => active_operation_mode_id,
"actuator_id" => actuator_id,
"message_id" => message_id,
"message_type" => message_type,
"operation_mode_factor" => operation_mode_factor,
"previous_operation_mode_id" => previous_operation_mode_id,
"transition_timestamp" => transition_timestamp,
}
end

def to_json(options = nil)
JSON.generate(to_dynamic, options)
end
end
end
end
122 changes: 122 additions & 0 deletions lib/s2/messages/frbc_fill_level_target_profile.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
module S2
module Messages
module MessageType
FRBCFillLevelTargetProfile = "FRBC.FillLevelTargetProfile"
end

# The target range in which the fill_level must be for the time period during which the
# element is active. The start of the range must be smaller or equal to the end of the
# range. The CEM must take best-effort actions to proactively achieve this target.
class NumberRange < Dry::Struct

# Number that defines the end of the range
attribute :end_of_range, Types::Double

# Number that defines the start of the range
attribute :start_of_range, Types::Double

def self.from_dynamic!(d)
d = Types::Hash[d]
new(
end_of_range: d.fetch("end_of_range"),
start_of_range: d.fetch("start_of_range"),
)
end

def self.from_json!(json)
from_dynamic!(JSON.parse(json))
end

def to_dynamic
{
"end_of_range" => end_of_range,
"start_of_range" => start_of_range,
}
end

def to_json(options = nil)
JSON.generate(to_dynamic, options)
end
end

class FRBCFillLevelTargetProfileElement < Dry::Struct

# The duration of the element.
attribute :duration, Types::Integer

# The target range in which the fill_level must be for the time period during which the
# element is active. The start of the range must be smaller or equal to the end of the
# range. The CEM must take best-effort actions to proactively achieve this target.
attribute :fill_level_range, NumberRange

def self.from_dynamic!(d)
d = Types::Hash[d]
new(
duration: d.fetch("duration"),
fill_level_range: NumberRange.from_dynamic!(d.fetch("fill_level_range")),
)
end

def self.from_json!(json)
from_dynamic!(JSON.parse(json))
end

def to_dynamic
{
"duration" => duration,
"fill_level_range" => fill_level_range.to_dynamic,
}
end

def to_json(options = nil)
JSON.generate(to_dynamic, options)
end
end

module MessageType
FRBCFillLevelTargetProfile = "FRBC.FillLevelTargetProfile"
end

class FrbcFillLevelTargetProfile < Dry::Struct

# List of different fill levels that have to be targeted within a given duration. There
# shall be at least one element. Elements must be placed in chronological order.
attribute :elements, Types.Array(FRBCFillLevelTargetProfileElement)

# ID of this message
attribute :message_id, Types::String

attribute :message_type, Types::MessageType

# Time at which the FRBC.FillLevelTargetProfile starts.
attribute :start_time, Types::String

def self.from_dynamic!(d)
d = Types::Hash[d]
new(
elements: d.fetch("elements").map { |x| FRBCFillLevelTargetProfileElement.from_dynamic!(x) },
message_id: d.fetch("message_id"),
message_type: d.fetch("message_type"),
start_time: d.fetch("start_time"),
)
end

def self.from_json!(json)
from_dynamic!(JSON.parse(json))
end

def to_dynamic
{
"elements" => elements.map { |x| x.to_dynamic },
"message_id" => message_id,
"message_type" => message_type,
"start_time" => start_time,
}
end

def to_json(options = nil)
JSON.generate(to_dynamic, options)
end
end
end
end
71 changes: 71 additions & 0 deletions lib/s2/messages/frbc_instruction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module S2
module Messages
module MessageType
FRBCInstruction = "FRBC.Instruction"
end

class FrbcInstruction < Dry::Struct

# Indicates if this is an instruction during an abnormal condition.
attribute :abnormal_condition, Types::Bool

# ID of the actuator this instruction belongs to.
attribute :actuator_id, Types::String

# Indicates the moment the execution of the instruction shall start. When the specified
# execution time is in the past, execution must start as soon as possible.
attribute :execution_time, Types::String

# ID of the instruction. Must be unique in the scope of the Resource Manager, for at least
# the duration of the session between Resource Manager and CEM.
attribute :id, Types::String

# ID of this message
attribute :message_id, Types::String

attribute :message_type, Types::MessageType

# ID of the FRBC.OperationMode that should be activated.
attribute :operation_mode, Types::String

# The number indicates the factor with which the FRBC.OperationMode should be configured.
# The factor should be greater than or equal to 0 and less or equal to 1.
attribute :operation_mode_factor, Types::Double

def self.from_dynamic!(d)
d = Types::Hash[d]
new(
abnormal_condition: d.fetch("abnormal_condition"),
actuator_id: d.fetch("actuator_id"),
execution_time: d.fetch("execution_time"),
id: d.fetch("id"),
message_id: d.fetch("message_id"),
message_type: d.fetch("message_type"),
operation_mode: d.fetch("operation_mode"),
operation_mode_factor: d.fetch("operation_mode_factor"),
)
end

def self.from_json!(json)
from_dynamic!(JSON.parse(json))
end

def to_dynamic
{
"abnormal_condition" => abnormal_condition,
"actuator_id" => actuator_id,
"execution_time" => execution_time,
"id" => id,
"message_id" => message_id,
"message_type" => message_type,
"operation_mode" => operation_mode,
"operation_mode_factor" => operation_mode_factor,
}
end

def to_json(options = nil)
JSON.generate(to_dynamic, options)
end
end
end
end
Loading