///|
pub let ether_type_profinet : Int = 0x8892
///|
pub let frame_id_get_set : Int = 65277
///|
pub let frame_id_identify_request : Int = 65278
///|
pub let dcp_service_id_get : Int = 3
///|
pub let dcp_service_id_set : Int = 4
///|
pub let dcp_service_id_identify : Int = 5
///|
pub let dcp_service_type_request : Int = 0
///|
pub let dcp_option_ip : Byte = 1
///|
pub let dcp_option_device : Byte = 2
///|
pub let dcp_option_dhcp : Byte = 3
///|
pub let dcp_option_control : Byte = 5
///|
pub let dcp_option_initiative : Byte = 6
///|
pub let dcp_option_all : Byte = 255
///|
pub let dcp_suboption_mac_address : Byte = 1
///|
pub let dcp_suboption_ip_parameter : Byte = 2
///|
pub let dcp_suboption_full_ip_suite : Byte = 3
///|
pub let dcp_suboption_device_vendor : Byte = 1
///|
pub let dcp_suboption_name_of_station : Byte = 2
///|
pub let dcp_suboption_device_id : Byte = 3
///|
pub let dcp_suboption_device_role : Byte = 4
///|
pub let dcp_suboption_device_options : Byte = 5
///|
pub let dcp_suboption_device_alias : Byte = 6
///|
pub let dcp_suboption_device_instance : Byte = 7
///|
pub let dcp_suboption_device_oem_id : Byte = 8
///|
pub let dcp_suboption_control_response : Byte = 4
///|
pub let dcp_suboption_device_initiative : Byte = 1
///|
pub let dcp_suboption_all : Byte = 255
///|
pub let frame_id_identify_response : Int = 65279
///|
fn push_u16_be(output : Array[Byte], value : Int) -> Unit {
output.push(((value >> 8) & 0xFF).to_byte())
output.push((value & 0xFF).to_byte())
}
///|
fn push_u32_be(output : Array[Byte], value : Int) -> Unit {
output.push(((value >> 24) & 0xFF).to_byte())
output.push(((value >> 16) & 0xFF).to_byte())
output.push(((value >> 8) & 0xFF).to_byte())
output.push((value & 0xFF).to_byte())
}
///|
fn append_bytes(output : Array[Byte], data : Bytes) -> Unit {
for byte in data {
output.push(byte)
}
}
///|
fn append_payload_block(
output : Array[Byte],
option : Byte,
suboption : Byte,
payload : Bytes,
) -> Unit {
output.push(option)
output.push(suboption)
push_u16_be(output, payload.length())
append_bytes(output, payload)
if payload.length() % 2 == 1 {
output.push(0)
}
}
///|
fn read_u16_be(data : Bytes, offset : Int) -> Int {
(data[offset].to_int() << 8) + data[offset + 1].to_int()
}
///|
fn read_u32_be(data : Bytes, offset : Int) -> Int {
(data[offset].to_int() << 24) +
(data[offset + 1].to_int() << 16) +
(data[offset + 2].to_int() << 8) +
data[offset + 3].to_int()
}
///|
fn bytes_slice(data : Bytes, start : Int, len : Int) -> Bytes {
Bytes::from_array(data.view(start~, end=start + len).to_array())
}
///|
fn encode_dcp_ethernet_frame(
destination : @frame.MacAddress,
source : @frame.MacAddress,
frame_id : Int,
service_id : Int,
service_type : Int,
xid : Int,
response_delay : Int,
payload : Bytes,
) -> Bytes {
let output : Array[Byte] = []
append_bytes(output, destination.octets())
append_bytes(output, source.octets())
push_u16_be(output, ether_type_profinet)
push_u16_be(output, frame_id)
output.push(service_id.to_byte())
output.push(service_type.to_byte())
push_u32_be(output, xid)
push_u16_be(output, response_delay)
push_u16_be(output, payload.length())
append_bytes(output, payload)
Bytes::from_array(output)
}