Skip to content

Commit

Permalink
Merge pull request #1 from ahmedMHasan/additional_sentences_v1
Browse files Browse the repository at this point in the history
Additional sentences v1
  • Loading branch information
ahmedMHasan authored Sep 5, 2023
2 parents a60cdb4 + 011d4ad commit 21e3c66
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ on [IEC 61162-1:2016 (Edition 5.0 2016-08)](https://webstore.iec.ch/publication/
| [ALR](./alr.go) | Set alarm state | |
| [APB](./apb.go) | Heading/track controller (autopilot) sentence B | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_apb_autopilot_sentence_b) |
| [ARC](./arc.go) | Alert command refused | |
| [AZT](./azt.go) | Azimuth Thruster message | |
| [BBM](./bbm.go) | AIS broadcast binary message | |
| [BEC](./bec.go) | Bearing and distance to waypoint, Dead reckoning | [1](http://www.nmea.de/nmea0183datensaetze.html#bec) |
| [BOD](./bod.go) | Bearing origin to destination | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_bod_bearing_waypoint_to_waypoint) |
Expand Down Expand Up @@ -95,6 +96,7 @@ on [IEC 61162-1:2016 (Edition 5.0 2016-08)](https://webstore.iec.ch/publication/
| LR3 | AIS long-range reply sentence 3 | |
| LRF | AIS long-range function | |
| LRI | AIS long-range interrogation | |
| [MCP](./mcp.go) | Micropilot Joystick controller message | |
| [MDA](./mda.go) | Meteorological Composite | [gpsd](https://gpsd.gitlab.io/gpsd/NMEA.html#_mda_meteorological_composite) |
| [MTA](./mta.go) | Air Temperature (obsolete, use XDR instead) | |
| MOB | Man over board notification | |
Expand Down
60 changes: 60 additions & 0 deletions azt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package nmea

const (
// TypeAZT type for AZT sentences
TypeAZT = "AZT"
)

// AZT - Azimuth Thruster Message
// Format: $--AZT,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x*hh<CR><LF>
// Example: $IIAZT,1,45.5,90.0,50.0,60.0,75.0,30.0,40.0,80.0,70.0,3,85.0,0,0,0,12345,9876,5432*2B
type AZT struct {
BaseSentence
ThrusterNo int64 // 1...9 Azimuth thruster number 1..9.
SteeringCommandSetValue float64 // 0...359.9 ° Steering command set value.
SteeringMeasurementActualValue float64 // 0...359.9 ° Steering measurement actual value.
PrimeMoverCommandSetValue float64 // -100...+100 % Prime mover (P.M.) RPM command set value. +100% equals nominal RPM (negative optional).
PrimeMoverMeasurementActualValue float64 // -100...+100 % P.M. RPM measurement actual value. +100% equals nominal RPM (negative optional).
VariableSlippingClutchCommandSetValue float64 // 0...100 % Variable slipping clutch command set value. 100% equals fully engaged clutch (no slipping), 0% equals clutch disengaged. <zero value if not used>.
PitchCommandSetValue float64 // -100...+100 % Pitch command set value. -100% equals max. negative pitch, 0% equals zero pitch, +100% equals max. positive pitch. <zero value if not used>.
PitchMeasurementActualValue float64 // -100...+100 % Pitch measurement actual value. <zero value if not used>.
PMLoadLimitSetValue float64 // 0...120 % P.M. load limit set value (LLS). <zero value if not used>.
PMLoadLimitCurrentMaxValue float64 // 0...120 % P.M. load limit current max. allowed value. <zero value if not used>.
PMLoadMeasurementActualValue float64 // 0...120 % P.M. load measurement actual value (FPS). <zero value if not used>.
ActiveControlStationNumber int64 // 0...9 Active control station number in range of 1…9. Value is zero if no control station is selected.
PropellerRPMMeasurementActualValue float64 // 0...100 % Propeller RPM measurement actual value. +100% equals nominal RPM (used with slipping clutch).
Reserved1 float64 // Reserved for future use. <zero value>.
Reserved2 float64 // Reserved for future use. <zero value>.
Reserved3 float64 // Reserved for future use. <zero value>.
ValueErrorStatusWord int64 // Value error status word for values 1...15, each bit indicates a single value error condition state either OK or ERROR.
ControlStateWord1 int64 // Control state word 1, each bit indicates a separate condition state either ON or OFF.
ControlStateWord2 int64 // Control state word 2 (pitch), each bit indicates a separate condition state either ON or OFF.
}

// newAZT constructor
func newAZT(s BaseSentence) (Sentence, error) {
p := NewParser(s)
p.AssertType(TypeAZT)
return AZT{
BaseSentence: s,
ThrusterNo: p.Int64(0, "x"),
SteeringCommandSetValue: p.Float64(1, "value1"),
SteeringMeasurementActualValue: p.Float64(2, "value2"),
PrimeMoverCommandSetValue: p.Float64(3, "value3"),
PrimeMoverMeasurementActualValue: p.Float64(4, "value4"),
VariableSlippingClutchCommandSetValue: p.Float64(5, "value5"),
PitchCommandSetValue: p.Float64(6, "value6"),
PitchMeasurementActualValue: p.Float64(7, "value7"),
PMLoadLimitSetValue: p.Float64(8, "value8"),
PMLoadLimitCurrentMaxValue: p.Float64(9, "value9"),
PMLoadMeasurementActualValue: p.Float64(10, "value10"),
ActiveControlStationNumber: p.Int64(11, "value11"),
PropellerRPMMeasurementActualValue: p.Float64(12, "value12"),
Reserved1: p.Float64(13, "value13"),
Reserved2: p.Float64(14, "value14"),
Reserved3: p.Float64(15, "value15"),
ValueErrorStatusWord: p.Int64(16, "vesw"),
ControlStateWord1: p.Int64(17, "csw1"),
ControlStateWord2: p.Int64(18, "csw2"),
}, p.Err()
}
61 changes: 61 additions & 0 deletions azt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package nmea

import (
"github.com/stretchr/testify/assert"
"testing"
)

var azttests = []struct {
name string
raw string
err string
msg AZT
}{
{
name: "good sentence",
raw: "$IIAZT,1,45.5,90.0,50.0,60.0,75.0,30.0,40.0,80.0,70.0,70.0,3,85.0,0,0,0,12345,9876,5432*70",
msg: AZT{
ThrusterNo: 1,
SteeringCommandSetValue: 45.5,
SteeringMeasurementActualValue: 90.0,
PrimeMoverCommandSetValue: 50.0,
PrimeMoverMeasurementActualValue: 60.0,
VariableSlippingClutchCommandSetValue: 75.0,
PitchCommandSetValue: 30.0,
PitchMeasurementActualValue: 40.0,
PMLoadLimitSetValue: 80.0,
PMLoadLimitCurrentMaxValue: 70.0,
PMLoadMeasurementActualValue: 70.0,
ActiveControlStationNumber: 3,
PropellerRPMMeasurementActualValue: 85.0,
Reserved1: 0,
Reserved2: 0,
Reserved3: 0,
ValueErrorStatusWord: 12345,
ControlStateWord1: 9876,
ControlStateWord2: 5432,
},
},
{
name: "bad validity",
raw: "$IIAZT,1,45.5,90.0,50.0,60.0,75.0,30.0,40.0,80.0,70.0,70.0,3,85.0,0,0,0,12345,9876,5432*74",
err: "nmea: sentence checksum mismatch [70 != 74]",
},
}

func TestAZT(t *testing.T) {
for _, tt := range azttests {
t.Run(tt.name, func(t *testing.T) {
m, err := Parse(tt.raw)
if tt.err != "" {
assert.Error(t, err)
assert.EqualError(t, err, tt.err)
} else {
assert.NoError(t, err)
azt := m.(AZT)
azt.BaseSentence = BaseSentence{}
assert.Equal(t, tt.msg, azt)
}
})
}
}
38 changes: 38 additions & 0 deletions mcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package nmea

const (
// TypeMCP type for MCP sentences
TypeMCP = "MCP"
)

// MCP - Micropilot Joystick Controller Message
// Format: $--MCP,x.x,f,x.x,f,x.x,f,x.x,f,x.x,f,x,i,x,i,x,i*hh<CR><LF>
// Example: $IIMCP,50.0,%f,30.0,%f,45.0,%f,0,0,0*hh
type MCP struct {
BaseSentence
JoystickSurgeAxisCommandSetValue float64 // Joystick surge axis (ahead - astern) command set value.
JoystickSwayAxisCommandSetValue float64 // Joystick sway axis (sideways port - sideways starboard) command set value.
JoystickYawAxisCommandSetValue float64 // Joystick yaw axis (rotation counter-clockwise - clockwise) command set value.
Reserved1 float64 // Reserved for future use.
Reserved2 float64 // Reserved for future use.
ValueErrorStatusWord int64 // Value error status word for values 1...5, each bit indicates a single value error condition state either OK or ERROR.
ControlStateWord1 int64 // Control state word 1, each bit indicates a separate condition state either ON or OFF.
ControlStateWord2 int64 // Control state word 2, each bit indicates a separate condition state either ON or OFF.
}

// newMCP constructor
func newMCP(s BaseSentence) (Sentence, error) {
p := NewParser(s)
p.AssertType(TypeMCP)
return MCP{
BaseSentence: s,
JoystickSurgeAxisCommandSetValue: p.Float64(0, "value1"),
JoystickSwayAxisCommandSetValue: p.Float64(1, "value2"),
JoystickYawAxisCommandSetValue: p.Float64(2, "value3"),
Reserved1: p.Float64(3, "value4"),
Reserved2: p.Float64(4, "value5"),
ValueErrorStatusWord: p.Int64(5, "vesw"),
ControlStateWord1: p.Int64(6, "csw1"),
ControlStateWord2: p.Int64(7, "csw2"),
}, p.Err()
}
50 changes: 50 additions & 0 deletions mcp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package nmea

import (
"github.com/stretchr/testify/assert"
"testing"
)

var mcptests = []struct {
name string
raw string
err string
msg MCP
}{
{
name: "good sentence",
raw: "$IIMCP,50.0,25.0,10.0,0,0,12345,9876,5432*72",
msg: MCP{
JoystickSurgeAxisCommandSetValue: 50.0,
JoystickSwayAxisCommandSetValue: 25.0,
JoystickYawAxisCommandSetValue: 10.0,
Reserved1: 0,
Reserved2: 0,
ValueErrorStatusWord: 12345,
ControlStateWord1: 9876,
ControlStateWord2: 5432,
},
},
{
name: "bad validity",
raw: "$IIMCP,50.0,25.0,10.0,0,0,12345,9876,5432*64",
err: "nmea: sentence checksum mismatch [72 != 64]",
},
}

func TestMCP(t *testing.T) {
for _, tt := range mcptests {
t.Run(tt.name, func(t *testing.T) {
m, err := Parse(tt.raw)
if tt.err != "" {
assert.Error(t, err)
assert.EqualError(t, err, tt.err)
} else {
assert.NoError(t, err)
mcp := m.(MCP)
mcp.BaseSentence = BaseSentence{}
assert.Equal(t, tt.msg, mcp)
}
})
}
}
4 changes: 4 additions & 0 deletions sentence.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,10 @@ func (p *SentenceParser) Parse(raw string) (Sentence, error) {
return newXDR(s)
case TypeXTE:
return newXTE(s)
case TypeMCP:
return newMCP(s)
case TypeAZT:
return newAZT(s)
}
}
if s.Raw[0] == SentenceStartEncapsulated[0] {
Expand Down

0 comments on commit 21e3c66

Please sign in to comment.