cleaned up develop and merged with refactoring

This commit is contained in:
Timo Volkmann 2020-12-03 15:09:33 +01:00
parent a3d5d7390d
commit bcdf7ddbf7
23 changed files with 732 additions and 495 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

6
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectPlainTextFileTypeManager">
<file url="file://$PROJECT_DIR$/gnet/net.go" />
</component>
</project>

1
.idea/vcs.xml generated
View File

@ -2,6 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library" vcs="Git" />
</component>
</project>

226
.idea/workspace.xml generated
View File

@ -16,85 +16,35 @@
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:sensor" type="e8cecc67:BranchNodeDescriptor" />
<item name="BRANCH:sensor/relative" type="e8cecc67:BranchNodeDescriptor" />
<item name="BRANCH:timo" type="e8cecc67:BranchNodeDescriptor" />
</path>
</select>
</component>
<component name="ChangeListManager">
<list default="true" id="99c957e4-aa42-481d-843d-3fbc901e0f79" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/cmd/serial_only/serial_only.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/serial_ubx/serial.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ublox/decode.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ublox/messages.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ublox/strings_navpvt.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/cmd/tcp_only/tcp_only.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/collectors.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/dispatcher.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/format.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/http.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/pipeline.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmd/serial_only/serial_only.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/serial_only/serial_only.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmd/server/server.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/server/server.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmd/server_only/server_only.go" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/dispatcher/dispatcher.go" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/ex_websocketMessage.json" beforeDir="false" afterPath="$PROJECT_DIR$/static/ex_websocketMessage.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" />
<change beforePath="$PROJECT_DIR$/hyperimu.json" beforeDir="false" afterPath="$PROJECT_DIR$/hyperimu.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/.gitattributes" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/.gitignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/CONTRIBUTING.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/ISSUE_TEMPLATE.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/LICENSE.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/README.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/Theory.md" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Dead Reckoning/Example1_calibrateSensor/Example1_calibrateSensor.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Dead Reckoning/Example2_getIMUData/Example2_getIMUData.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Dead Reckoning/Example3_getSensorStatus/Example3_getSensorStatus.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Dead Reckoning/Example4_vehicleDynamics/Example4_vehicleDynamics.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example10_AltitudeMSL/Example10_AltitudeMSL.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example11_ResetModule/Example1_FactoryDefaultviaI2C/Example1_FactoryDefaultviaI2C.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example11_ResetModule/Example2_FactoryDefaultsviaSerial/Example2_FactoryDefaultsviaSerial.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example12_UseUart/Example12_UseUart.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example13_PVT/Example1_AutoPVT/Example1_AutoPVT.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example13_PVT/Example2_AutoPVT_ExplicitUpdate/Example2_AutoPVT_ExplicitUpdate.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example13_PVT/Example3_AssumeAutoPVTviaUart/Example3_AssumeAutoPVTviaUart.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example14_DebugOutput/Example14_DebugOutput.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example15_GetDateTime/Example15_GetDateTime.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example16_Nanosecond_MaxOutput/Example16_Nanosecond_MaxOutput.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example16_PartialSecond_MaxOutput/Example16_PartialSecond_MaxOutput.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example17_Geofence/Example17_Geofence.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example18_PowerSaveMode/Example18_PowerSaveMode.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example19_DynamicModel/Example19_DynamicModel.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example1_BasicNMEARead/Example1_BasicNMEARead.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example20_SendCustomCommand/Example20_SendCustomCommand.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example21_ModuleInfo/Example21_ModuleInfo.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example22_PowerOff/Example22_PowerOff.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example2_NMEAParsing/Example2_NMEAParsing.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example3_GetPosition/Example3_GetPosition.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example4_FixType/Example4_FixType.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example5_SpeedHeadingPrecision/Example5_SpeedHeadingPrecision.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example6_EnableNMEASentences/Example6_EnableNMEASentences.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example7_OutputRate/Example7_OutputRate.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example8_GetProtocolVersion/Example8_GetProtocolVersion.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Example9_ChangeI2CAddress/Example9_ChangeI2CAddress.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/NEO-M8P-2/Example1_EnableRTCM/Example1_EnableRTCM.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/NEO-M8P-2/Example2_StartRTCMBase/Example2_StartRTCMBase.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/NEO-M8P-2/Example3_BaseWithLCD/Example3_BaseWithLCD.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Series_6_7/Example1_GetPositionAndTime_Series_6_7/Example1_GetPositionAndTime_Series_6_7.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Series_6_7/Example1_GetPositionAndTime_Series_6_7/SparkFun_Ublox_Arduino_Library_Series_6_7.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/Series_6_7/Example1_GetPositionAndTime_Series_6_7/SparkFun_Ublox_Arduino_Library_Series_6_7.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example10_GetHighPrecisionPositionAndAccuracy/Example10_GetHighPrecisionPositionAndAccuracy.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example11_GetHighPrecisionPositionUsingDouble/Example11_GetHighPrecisionPositionUsingDouble.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example11_autoHPPOSLLH/Example11_autoHPPOSLLH.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example11_setStaticPosition/Example11_setStaticPosition.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example1_GetPositionAccuracy/Example1_GetPositionAccuracy.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example2_ValConfigurationMethod/Example2_ValConfigurationMethod.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example3_StartRTCMBase/Example3_StartRTCMBase.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example4_BaseWithLCD/Example4_BaseWithLCD.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example5_RelativePositioningInformation/Example5_RelativePositioningInformation.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example6_GetVal/Example6_GetVal.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example7_SetVal/Example7_SetVal.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example8_GetSetPortSettings/Example8_GetSetPortSettings.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/examples/ZED-F9P/Example9_multiSetVal/Example9_multiSetVal.ino" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/keywords.txt" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/library.properties" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/src/SparkFun_Ublox_Arduino_Library.cpp" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/src/SparkFun_Ublox_Arduino_Library.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library/src/u-blox_config_keys.h" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial/serial.go" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/server.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/server/server.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/hyperimu.json" beforeDir="false" afterPath="$PROJECT_DIR$/static/hyperimu.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/static/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/net/net.go" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/serial_ubx/serial.go" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/ublox/decode.go" beforeDir="false" afterPath="$PROJECT_DIR$/ublox/decode.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ublox/messages.go" beforeDir="false" afterPath="$PROJECT_DIR$/ublox/messages.go" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -109,7 +59,7 @@
</list>
</option>
</component>
<component name="GOROOT" path="/usr/local/Cellar/go/1.15.2/libexec" />
<component name="GOROOT" path="/usr/local/Cellar/go/1.15.5/libexec" />
<component name="Git.Settings">
<option name="RECENT_BRANCH_BY_REPOSITORY">
<map>
@ -135,18 +85,18 @@
<property name="go.sdk.automatically.set" value="true" />
<property name="go.tried.to.enable.integration.vgo.integrator" value="true" />
<property name="last_opened_file_path" value="$USER_HOME$" />
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
<property name="settings.editor.selected.configurable" value="project.propVCSSupport.Mappings" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/static" />
<recent name="$PROJECT_DIR$/core" />
<recent name="$PROJECT_DIR$/net" />
<recent name="$PROJECT_DIR$/cmd/server" />
<recent name="$PROJECT_DIR$/serial_ubx" />
<recent name="$PROJECT_DIR$" />
<recent name="$PROJECT_DIR$/ublox" />
<recent name="$PROJECT_DIR$/serial" />
</key>
</component>
<component name="RunManager" selected="Go Build.go build git.timovolkmann.de/gyrogpsc/cmd/serial_only">
<component name="RunManager" selected="Go Build.go build git.timovolkmann.de/gyrogpsc/cmd/server">
<configuration name="go build git.timovolkmann.de/gyrogpsc/cmd/serial_only" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="gyrogpsc" />
<working_directory value="$PROJECT_DIR$" />
@ -156,6 +106,15 @@
<directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<configuration name="go build git.timovolkmann.de/gyrogpsc/cmd/server" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="gyrogpsc" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<filePath value="$PROJECT_DIR$/cmd/server/server.go" />
<package value="git.timovolkmann.de/gyrogpsc/cmd/server" />
<directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<configuration name="go build git.timovolkmann.de/gyrogpsc/serial" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="gyrogpsc" />
<working_directory value="$PROJECT_DIR$" />
@ -165,6 +124,14 @@
<directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<configuration name="go build server.go (1)" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="gyrogpsc" />
<working_directory value="$PROJECT_DIR$" />
<kind value="FILE" />
<filePath value="$PROJECT_DIR$/cmd/server/server.go" />
<directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<configuration name="go build server.go" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="gyrogpsc" />
<working_directory value="$PROJECT_DIR$" />
@ -175,11 +142,7 @@
</configuration>
<recent_temporary>
<list>
<item itemvalue="Go Build.go build git.timovolkmann.de/gyrogpsc/cmd/serial_only" />
<item itemvalue="Go Build.go build git.timovolkmann.de/gyrogpsc/serial" />
<item itemvalue="Go Build.go build server.go" />
<item itemvalue="Go Build.go build server.go" />
<item itemvalue="Go Build.go build git.timovolkmann.de/gyrogpsc/serial" />
<item itemvalue="Go Build.go build git.timovolkmann.de/gyrogpsc/cmd/server" />
</list>
</recent_temporary>
</component>
@ -227,7 +190,21 @@
<option name="project" value="LOCAL" />
<updated>1605444355479</updated>
</task>
<option name="localTasksCounter" value="6" />
<task id="LOCAL-00006" summary="refactored cmd &amp; server">
<created>1606332601566</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1606332601566</updated>
</task>
<task id="LOCAL-00007" summary="refactor and implemented data pipeline">
<created>1606934501184</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1606934501184</updated>
</task>
<option name="localTasksCounter" value="8" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -239,12 +216,17 @@
<entry key="MAIN">
<value>
<State>
<option name="CUSTOM_BOOLEAN_PROPERTIES">
<map>
<entry key="Show.Git.Branches" value="true" />
</map>
</option>
<option name="FILTERS">
<map>
<entry key="branch">
<value>
<list>
<option value="sensor/relative" />
<option value="timo" />
</list>
</value>
</entry>
@ -258,25 +240,42 @@
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="VcsManagerConfiguration">
<ignored-roots>
<path value="$PROJECT_DIR$/serial/SparkFun_Ublox_Arduino_Library" />
</ignored-roots>
<MESSAGE value="initial working version" />
<MESSAGE value="added dispatcher.go" />
<MESSAGE value="3d orientation visualization html/css" />
<MESSAGE value="switched to relative sensor data (gyroscope)" />
<MESSAGE value="changed orientation" />
<option name="LAST_COMMIT_MESSAGE" value="changed orientation" />
<MESSAGE value="refactored cmd &amp; server" />
<MESSAGE value="refactor and implemented data pipeline" />
<option name="LAST_COMMIT_MESSAGE" value="refactor and implemented data pipeline" />
</component>
<component name="VgoProject">
<integration-enabled>true</integration-enabled>
</component>
<component name="WindowStateProjectService">
<state x="756" y="546" key="#GOROOT" timestamp="1606935753174">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state x="756" y="546" key="#GOROOT/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606935753174" />
<state x="640" y="377" key="#Go_Modules" timestamp="1604584628285">
<screen x="0" y="23" width="1680" height="1027" />
</state>
<state x="640" y="377" key="#Go_Modules/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604584628285" />
<state x="523" y="282" key="#com.intellij.openapi.keymap.impl.ui.EditKeymapsDialog" timestamp="1606822254644">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state x="523" y="282" key="#com.intellij.openapi.keymap.impl.ui.EditKeymapsDialog/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606822254644" />
<state x="603" y="247" key="#xdebugger.evaluate" timestamp="1604750409547">
<screen x="0" y="23" width="1680" height="1027" />
</state>
<state x="603" y="247" key="#xdebugger.evaluate/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604750409547" />
<state width="595" height="466" key="DebuggerActiveHint" timestamp="1606953226425">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state width="595" height="466" key="DebuggerActiveHint/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606953226425" />
<state x="100" y="123" width="1480" height="827" key="DiffContextDialog" timestamp="1604517986662">
<screen x="0" y="23" width="1680" height="1027" />
</state>
@ -301,46 +300,50 @@
<screen x="0" y="23" width="1680" height="1027" />
</state>
<state width="1638" height="346" key="GridCell.Tab.-1.right/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604750445987" />
<state width="1878" height="249" key="GridCell.Tab.0.bottom" timestamp="1606326600270">
<screen x="0" y="23" width="1920" height="1177" />
<state width="1878" height="402" key="GridCell.Tab.0.bottom" timestamp="1606957947578">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state width="1638" height="273" key="GridCell.Tab.0.bottom/0.-1417.2560.1417/0.23.1680.1027@0.-1417.2560.1417" timestamp="1604948042531" />
<state width="1638" height="273" key="GridCell.Tab.0.bottom/0.23.1680.1027/0.-1417.2560.1417@0.-1417.2560.1417" timestamp="1604913985770" />
<state width="1638" height="273" key="GridCell.Tab.0.bottom/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604760252890" />
<state width="1638" height="273" key="GridCell.Tab.0.bottom/0.23.1680.1027@0.23.1680.1027" timestamp="1604933111805" />
<state width="1638" height="273" key="GridCell.Tab.0.bottom/0.23.1920.1116@0.23.1920.1116" timestamp="1605380018474" />
<state width="1878" height="249" key="GridCell.Tab.0.bottom/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606326600270" />
<state width="1878" height="406" key="GridCell.Tab.0.bottom/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606335310969" />
<state width="1638" height="273" key="GridCell.Tab.0.bottom/0.23.1920.1177@0.23.1920.1177" timestamp="1605533225921" />
<state width="1878" height="249" key="GridCell.Tab.0.center" timestamp="1606326600270">
<screen x="0" y="23" width="1920" height="1177" />
<state width="1878" height="402" key="GridCell.Tab.0.bottom/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606957947578" />
<state width="1878" height="402" key="GridCell.Tab.0.center" timestamp="1606957947577">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state width="1638" height="273" key="GridCell.Tab.0.center/0.-1417.2560.1417/0.23.1680.1027@0.-1417.2560.1417" timestamp="1604948042530" />
<state width="1638" height="273" key="GridCell.Tab.0.center/0.23.1680.1027/0.-1417.2560.1417@0.-1417.2560.1417" timestamp="1604913985769" />
<state width="1638" height="273" key="GridCell.Tab.0.center/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604760252890" />
<state width="1638" height="273" key="GridCell.Tab.0.center/0.23.1680.1027@0.23.1680.1027" timestamp="1604933111805" />
<state width="1638" height="273" key="GridCell.Tab.0.center/0.23.1920.1116@0.23.1920.1116" timestamp="1605380018473" />
<state width="1878" height="249" key="GridCell.Tab.0.center/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606326600270" />
<state width="1878" height="406" key="GridCell.Tab.0.center/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606335310968" />
<state width="1638" height="273" key="GridCell.Tab.0.center/0.23.1920.1177@0.23.1920.1177" timestamp="1605533225920" />
<state width="1878" height="249" key="GridCell.Tab.0.left" timestamp="1606326600269">
<screen x="0" y="23" width="1920" height="1177" />
<state width="1878" height="402" key="GridCell.Tab.0.center/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606957947577" />
<state width="1878" height="402" key="GridCell.Tab.0.left" timestamp="1606957947577">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state width="1638" height="273" key="GridCell.Tab.0.left/0.-1417.2560.1417/0.23.1680.1027@0.-1417.2560.1417" timestamp="1604948042530" />
<state width="1638" height="273" key="GridCell.Tab.0.left/0.23.1680.1027/0.-1417.2560.1417@0.-1417.2560.1417" timestamp="1604913985768" />
<state width="1638" height="273" key="GridCell.Tab.0.left/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604760252889" />
<state width="1638" height="273" key="GridCell.Tab.0.left/0.23.1680.1027@0.23.1680.1027" timestamp="1604933111805" />
<state width="1638" height="273" key="GridCell.Tab.0.left/0.23.1920.1116@0.23.1920.1116" timestamp="1605380018472" />
<state width="1878" height="249" key="GridCell.Tab.0.left/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606326600269" />
<state width="1878" height="406" key="GridCell.Tab.0.left/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606335310967" />
<state width="1638" height="273" key="GridCell.Tab.0.left/0.23.1920.1177@0.23.1920.1177" timestamp="1605533225919" />
<state width="1878" height="249" key="GridCell.Tab.0.right" timestamp="1606326600270">
<screen x="0" y="23" width="1920" height="1177" />
<state width="1878" height="402" key="GridCell.Tab.0.left/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606957947577" />
<state width="1878" height="402" key="GridCell.Tab.0.right" timestamp="1606957947578">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state width="1638" height="273" key="GridCell.Tab.0.right/0.-1417.2560.1417/0.23.1680.1027@0.-1417.2560.1417" timestamp="1604948042531" />
<state width="1638" height="273" key="GridCell.Tab.0.right/0.23.1680.1027/0.-1417.2560.1417@0.-1417.2560.1417" timestamp="1604913985770" />
<state width="1638" height="273" key="GridCell.Tab.0.right/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604760252890" />
<state width="1638" height="273" key="GridCell.Tab.0.right/0.23.1680.1027@0.23.1680.1027" timestamp="1604933111805" />
<state width="1638" height="273" key="GridCell.Tab.0.right/0.23.1920.1116@0.23.1920.1116" timestamp="1605380018473" />
<state width="1878" height="249" key="GridCell.Tab.0.right/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606326600270" />
<state width="1878" height="406" key="GridCell.Tab.0.right/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606335310968" />
<state width="1638" height="273" key="GridCell.Tab.0.right/0.23.1920.1177@0.23.1920.1177" timestamp="1605533225920" />
<state width="1878" height="402" key="GridCell.Tab.0.right/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606957947578" />
<state width="1638" height="346" key="GridCell.Tab.1.bottom" timestamp="1604750442086">
<screen x="0" y="23" width="1680" height="1027" />
</state>
@ -357,22 +360,43 @@
<screen x="0" y="23" width="1680" height="1027" />
</state>
<state width="1638" height="346" key="GridCell.Tab.1.right/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604750442085" />
<state x="204" y="155" width="1501" height="766" key="SettingsEditor" timestamp="1605609479939">
<screen x="0" y="23" width="1920" height="1177" />
<state x="204" y="157" width="1501" height="766" key="SettingsEditor" timestamp="1606924055987">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state x="179" y="138" width="1501" height="766" key="SettingsEditor/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604757277174" />
<state x="204" y="155" key="SettingsEditor/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1605609479939" />
<state x="204" y="157" key="SettingsEditor/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606924055987" />
<state x="560" y="351" key="Vcs.Push.Dialog.v2" timestamp="1606332623194">
<screen x="0" y="23" width="1920" height="1177" />
</state>
<state x="560" y="351" key="Vcs.Push.Dialog.v2/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606332623194" />
<state width="840" height="513" key="XDebugger.FullValuePopup" timestamp="1604750505120">
<screen x="0" y="23" width="1680" height="1027" />
</state>
<state width="840" height="513" key="XDebugger.FullValuePopup/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604750505120" />
<state x="505" y="250" width="670" height="676" key="search.everywhere.popup" timestamp="1604757918385">
<screen x="0" y="23" width="1680" height="1027" />
<state x="661" y="245" width="597" height="735" key="find.popup" timestamp="1606955246024">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state x="661" y="245" width="597" height="735" key="find.popup/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606955246024" />
<state x="694" y="331" key="git4idea.branch.GitSmartOperationDialog" timestamp="1606335339469">
<screen x="0" y="23" width="1920" height="1177" />
</state>
<state x="694" y="331" key="git4idea.branch.GitSmartOperationDialog/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1606335339469" />
<state x="577" y="285" width="766" height="774" key="search.everywhere.popup" timestamp="1606957420261">
<screen x="0" y="25" width="1920" height="1175" />
</state>
<state x="505" y="250" width="670" height="676" key="search.everywhere.popup/0.23.1680.1027/0.-1417.2560.1417@0.23.1680.1027" timestamp="1604757918385" />
<state x="577" y="285" width="766" height="774" key="search.everywhere.popup/0.25.1920.1175/0.-1415.2560.1415@0.25.1920.1175" timestamp="1606957420261" />
<state x="596" y="393" key="vcs.readOnlyHandler.ReadOnlyStatusDialog" timestamp="1605566567276">
<screen x="0" y="23" width="1920" height="1177" />
</state>
<state x="596" y="393" key="vcs.readOnlyHandler.ReadOnlyStatusDialog/0.23.1920.1177/0.-1417.2560.1417@0.23.1920.1177" timestamp="1605566567276" />
</component>
<component name="XDebuggerManager">
<watches-manager>
<configuration name="GoApplicationRunConfiguration">
<watch expression="*(*&quot;&lt;-chan time.Time&quot;)(824634171712)" />
</configuration>
</watches-manager>
</component>
</project>

View File

@ -1,14 +1,21 @@
package main
import (
"git.timovolkmann.de/gyrogpsc/serial_ubx"
"log"
"fmt"
"git.timovolkmann.de/gyrogpsc/core"
)
const (
SERIAL_PORT = "/dev/tty.usbmodem14201"
)
func main() {
r, err := serial_ubx.Setup("/dev/tty.usbmodem14201")
if err != nil {
log.Fatal(err)
}
r.Printloop()
core.SerialCollector(&printer{}, SERIAL_PORT)
}
type printer struct{}
func (p *printer) Process(data *core.Sensordata) error {
fmt.Println(data)
return nil
}

View File

@ -1,8 +1,8 @@
package main
import (
"git.timovolkmann.de/gyrogpsc/dispatcher"
gnet "git.timovolkmann.de/gyrogpsc/net"
"git.timovolkmann.de/gyrogpsc/core"
"log"
)
const (
@ -12,14 +12,20 @@ const (
)
func main() {
d := dispatcher.New()
collectRoutines(d)
gnet.NewHttpServer(d, HTTP_PORT)
log.Println("setup dispatcher")
dispatcher := core.NewDispatcher()
log.Println("initialize processing pipeline")
processor := core.NewPipeline(dispatcher, 50, 1000)
processor.Run()
log.Println("start data collectors")
collectRoutines(processor)
log.Println("start http server")
core.HttpListenAndServe(dispatcher, HTTP_PORT)
}
func collectRoutines(d *dispatcher.Dispatcher) {
// collectRoutines Serial UBX Sensor Data
go gnet.SerialUbxCollector(d, SERIAL_PORT)
// collectRoutines TCP JSON Sensor Data
go gnet.TcpJsonCollector(d, TCP_PORT)
func collectRoutines(proc core.Processor) {
// collect Sensor data from Serial UBX in Goroutine
go core.SerialCollector(proc, SERIAL_PORT)
// collect Sensor data from JSON over TCP in Goroutine
go core.TcpCollector(proc, TCP_PORT)
}

View File

@ -1,25 +0,0 @@
package main
import (
"git.timovolkmann.de/gyrogpsc/dispatcher"
gnet "git.timovolkmann.de/gyrogpsc/net"
)
const (
TCP_PORT = ":3010"
HTTP_PORT = ":3011"
SERIAL_PORT = "/dev/tty.usbmodem14201"
)
func main() {
d := dispatcher.New()
collectRoutines(d)
gnet.NewHttpServer(d, HTTP_PORT)
}
func collectRoutines(d *dispatcher.Dispatcher) {
// collectRoutines Serial UBX Sensor Data
go gnet.SerialUbxCollector(d, SERIAL_PORT)
// collectRoutines TCP JSON Sensor Data
go gnet.TcpJsonCollector(d, TCP_PORT)
}

22
cmd/tcp_only/tcp_only.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"git.timovolkmann.de/gyrogpsc/core"
)
const (
TCP_PORT = ":3010"
HTTP_PORT = ":3011"
)
func main() {
dispatcher := core.NewDispatcher()
processor := core.NewPipeline(dispatcher, 20, 10000)
collectRoutines(processor)
core.HttpListenAndServe(dispatcher, HTTP_PORT)
}
func collectRoutines(proc core.Processor) {
// collect Sensor data from JSON over TCP in Goroutine
go core.TcpCollector(proc, TCP_PORT)
}

98
core/collectors.go Normal file
View File

@ -0,0 +1,98 @@
package core
import (
"fmt"
"git.timovolkmann.de/gyrogpsc/ublox"
"go.bug.st/serial"
"log"
"net"
"os"
)
func TcpCollector(proc Processor, tcpPort string) {
listener, err := net.Listen("tcp", tcpPort)
if err != nil {
fmt.Println("Error listening:", err.Error())
os.Exit(1)
}
// Close the listener when the application closes.
defer listener.Close()
for {
// Listen for an incoming connection.
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}
// Handle connections in a new goroutine.
go jsonHandler(conn, proc)
}
}
// handles incoming tcp connections with json payload.
func jsonHandler(conn net.Conn, proc Processor) {
defer conn.Close()
// TRY reader := bufio.NewReader(conn) OR NewScanner(conn)
buf := make([]byte, 2048)
for {
// Read the incoming connection into the buffer.
n, err := conn.Read(buf)
if err != nil {
fmt.Println("TCP error - reading from connection:", n, err.Error())
break
}
//json := pretty.Pretty(buf[:n])
//fmt.Println(string(json))
fmt.Println(string(buf[:n]))
sd, err := ConvertSensorDataPhone(buf[:n])
if err != nil {
log.Println(err)
continue
}
err = proc.Process(sd)
if err != nil {
log.Println(err)
continue
}
}
}
func SerialCollector(proc Processor, serialPort string) {
mode := &serial.Mode{
BaudRate: 115200,
}
port, err := serial.Open(serialPort, mode)
if err != nil {
log.Fatalln(err.Error())
}
decoder := ublox.NewDecoder(port)
for {
meas, err := decoder.Decode()
if err != nil {
if err.Error() == "NMEA not implemented" {
continue
}
log.Println(err)
continue
}
sd, err := ConvertUbxToSensorData(meas)
if err != nil {
log.Println("convert err:", err, meas)
continue
}
if sd == nil {
continue
}
err = proc.Process(sd)
if err != nil {
log.Println("process err:", err, *sd)
continue
}
}
}

52
core/dispatcher.go Normal file
View File

@ -0,0 +1,52 @@
package core
import (
"errors"
"log"
)
type Subscriber interface {
Subscribe() (int16, <-chan string)
Unsubscribe(id int16) error
}
type Publisher interface {
Publish(message string)
}
type dispatcher struct {
listeners map[int16]chan string
counter int16
}
func NewDispatcher() *dispatcher {
return &dispatcher{
listeners: make(map[int16]chan string),
counter: 0,
}
}
func (d *dispatcher) Publish(message string) {
log.Printf("publish to %v listeners:\n%v\n", len(d.listeners), message)
for _, ch := range d.listeners {
ch <- message
}
}
func (d *dispatcher) Subscribe() (id int16, receiver <-chan string) {
key := d.counter
d.counter++
rec := make(chan string)
d.listeners[key] = rec
return key, rec
}
func (d *dispatcher) Unsubscribe(id int16) error {
receiver, ok := d.listeners[id]
if !ok {
return errors.New("no subscription with id")
}
delete(d.listeners, id)
close(receiver)
return nil
}

135
core/format.go Normal file
View File

@ -0,0 +1,135 @@
package core
import (
"errors"
"git.timovolkmann.de/gyrogpsc/ublox"
"log"
"time"
"github.com/m7shapan/njson"
)
/*{
"smartphone": {
// hier daten von hyperimu
},
"serial": {
// hier Daten von M8U:
"timestamp": 37539672354
"position": [0, 0, 0],
"orientation": [0, 0, 0]
}
}
*/
type sourceId string
const (
SOURCE_TCP sourceId = "SOURCE_TCP"
SOURCE_SERIAL sourceId = "SOURCE_SERIAL"
)
type Sensordata struct {
itow uint32
SourceId sourceId
Timestamp int64
Position [3]float64
Orientation [3]float64
}
func (s Sensordata) isSameEpoch(n Sensordata) bool {
if n.itow == 0 {
return false
}
return s.itow == n.itow
}
func (s Sensordata) Consolidate(n Sensordata) Sensordata {
if (s.SourceId != n.SourceId && s != Sensordata{}) {
log.Println(s)
log.Println(n)
log.Fatalln("Do not consolidate Sensordata from different Sources")
}
if s.isSameEpoch(n) {
null := Sensordata{}
//if s.Timestamp == null.Timestamp { s.Timestamp = n.Timestamp }
//if s.Position == null.Position { s.Position = n.Position }
//if s.Orientation == null.Orientation { s.Orientation = n.Orientation }
if n.Timestamp != null.Timestamp && s.Timestamp != n.Timestamp {
s.Timestamp = n.Timestamp
}
if n.Position != null.Position && s.Position != n.Position {
s.Position = n.Position
}
if n.Orientation != null.Orientation && s.Orientation != n.Orientation {
s.Orientation = n.Orientation
}
return s
}
return n
}
var (
errNotImplemented = errors.New("message not implemented")
errRawMessage = errors.New("raw message")
)
func ConvertUbxToSensorData(msg interface{}) (*Sensordata, error) {
sd := &Sensordata{
SourceId: SOURCE_SERIAL,
}
switch v := msg.(type) {
case *ublox.NavPvt:
//log.Println("NAV-PVT")
sd.itow = v.ITOW_ms
sd.Timestamp = time.Date(int(v.Year_y), time.Month(v.Month_month), int(v.Day_d), int(v.Hour_h), int(v.Min_min), int(v.Sec_s), int(v.Nano_ns), time.UTC).UnixNano()
sd.Position[0] = float64(v.Lat_dege7)
sd.Position[1] = float64(v.Lon_dege7)
sd.Position[2] = float64(v.Height_mm)
case *ublox.HnrPvt:
//log.Println("HNR-PVT")
sd.itow = v.ITOW_ms
sd.Timestamp = time.Date(int(v.Year_y), time.Month(v.Month_month), int(v.Day_d), int(v.Hour_h), int(v.Min_min), int(v.Sec_s), int(v.Nano_ns), time.UTC).UnixNano()
sd.Position[0] = float64(v.Lat_dege7)
sd.Position[1] = float64(v.Lon_dege7)
sd.Position[2] = float64(v.Height_mm)
case *ublox.NavAtt:
//log.Println("NAV-ATT")
sd.itow = v.ITOW_ms
sd.Orientation[0] = float64(v.Pitch_deg)
sd.Orientation[1] = float64(v.Roll_deg)
sd.Orientation[2] = float64(v.Heading_deg)
case *ublox.RawMessage:
//class := make([]byte, 2)
//binary.LittleEndian.PutUint16(class, v.ClassID())
//log.Printf("%#v, %#v", class[0],class[1])
return nil, nil
default:
return nil, errNotImplemented
}
return sd, nil
}
func ConvertSensorDataPhone(jsonData []byte) (*Sensordata, error) {
return convertAndroidHyperImu(jsonData)
}
func convertAndroidHyperImu(jsonData []byte) (*Sensordata, error) {
prep := struct {
Timestamp int64 `njson:"Timestamp"`
Position [3]float64 `njson:"GPS"`
Orientation [3]float64 `njson:"orientation"`
}{}
err := njson.Unmarshal(jsonData, &prep)
if err != nil {
return nil, err
}
sd := &Sensordata{
Timestamp: prep.Timestamp * int64(time.Millisecond),
//Timestamp: time.Unix(0, prep.Timestamp * int64(time.Millisecond)),
Position: prep.Position,
Orientation: prep.Orientation,
}
return sd, nil
}

71
core/http.go Normal file
View File

@ -0,0 +1,71 @@
package core
import (
"fmt"
"github.com/gorilla/websocket"
"html/template"
"log"
"net/http"
)
func echo(sub Subscriber) func(w http.ResponseWriter, r *http.Request) {
var upgrader = websocket.Upgrader{} // use default options
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("upgrading to ws")
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
//defer c.Close()
go func() {
for {
if _, _, err := c.NextReader(); err != nil {
c.Close()
break
}
}
}()
dispatcherId, channel := sub.Subscribe()
defer sub.Unsubscribe(dispatcherId)
for {
log.Println("")
//if err != nil {
// log.Println("read:", err)
// break
//}
cmsg := <-channel
err = c.WriteMessage(websocket.TextMessage, []byte(cmsg))
if err != nil {
log.Println("write:", err)
break
}
}
}
}
func home(w http.ResponseWriter, r *http.Request) {
//var homeTemplate = template.Must(template.NewDispatcher("").ParseFiles("index.html"))
tpl, err := template.ParseFiles("static/index.html")
if err != nil {
log.Fatalln(err)
}
err = tpl.Execute(w, "ws://"+r.Host+"/echo")
if err != nil {
log.Fatalln(err)
}
}
func HttpListenAndServe(sub Subscriber, httpPort string) {
log.Println("register websocket handler")
http.HandleFunc("/echo", echo(sub))
log.Println("register index handler")
http.HandleFunc("/", home)
log.Println("register static file handler")
http.Handle("/static/", http.FileServer(http.Dir(".")))
log.Println("start server")
log.Fatal(http.ListenAndServe(httpPort, nil))
}

150
core/pipeline.go Normal file
View File

@ -0,0 +1,150 @@
package core
import (
"encoding/json"
"errors"
"log"
"sync"
"time"
)
// TODO: adapt HNR-INS data to continue orientation stream
type Processor interface {
Process(data *Sensordata) error
}
type pipeline struct {
synchronizer
aggregator
Publisher
publishTicker *time.Ticker
}
func NewPipeline(d Publisher, publishIntervalMs int, delayUpdateIntervalMs int) *pipeline {
return &pipeline{
synchronizer{
bufferSize: 100,
mutex: &sync.Mutex{},
updateTicker: time.NewTicker(time.Duration(delayUpdateIntervalMs) * time.Millisecond),
},
aggregator{
tcpMutex: &sync.Mutex{},
serialMutex: &sync.Mutex{},
},
d,
time.NewTicker(time.Duration(publishIntervalMs) * time.Millisecond),
}
}
func (p *pipeline) Run() {
go p.schedule()
go func() {
for {
<-p.publishTicker.C
err := p.Publish()
if err != nil /*&& err.Error() != "no data available"*/ {
log.Println(err)
}
}
}()
log.Println("pipeline: processing service started")
}
func (p *pipeline) Publish() error {
p.tcpMutex.Lock()
p.serialMutex.Lock()
//log.Println(p.tcpSensorData)
//log.Println(p.serialSensorData)
if (p.tcpSensorData == Sensordata{} && p.serialSensorData == Sensordata{}) {
p.tcpMutex.Unlock()
p.serialMutex.Unlock()
return errors.New("no data available")
}
data := map[string]Sensordata{
string(SOURCE_TCP): p.tcpSensorData,
string(SOURCE_SERIAL): p.serialSensorData,
}
p.tcpSensorData = Sensordata{}
p.serialSensorData = Sensordata{}
p.tcpMutex.Unlock()
p.serialMutex.Unlock()
jdata, err := json.Marshal(data)
log.Println(string(jdata))
if err != nil {
return err
}
p.Publisher.Publish(string(jdata))
return nil
}
type aggregator struct {
tcpSensorData Sensordata
serialSensorData Sensordata
tcpMutex *sync.Mutex
serialMutex *sync.Mutex
}
type UnixNanoTime int64
type synchronizer struct {
tcpDelayMs int
serialDelayMs int
tcpBuffer map[UnixNanoTime]Sensordata
serialBuffer map[UnixNanoTime]Sensordata
bufferSize int
mutex *sync.Mutex
updateTicker *time.Ticker
// should run concurrently
//
// Methods:
// pushSensordata(Sensordata), remove oldest if larger than bufferSize
// refreshDelay()
// Schedule()
}
func (s *synchronizer) schedule() {
log.Println("synchronizer: started")
for {
<-s.updateTicker.C
err := s.refreshDelay()
if err != nil {
log.Println(err)
}
}
}
func (s *synchronizer) refreshDelay() error {
// TODO: implement
return nil
}
func (p *pipeline) Process(data *Sensordata) error {
if data == nil {
return errors.New("nil processing not allowed")
}
//log.Println(string(data.SourceId))
switch data.SourceId {
case SOURCE_TCP:
go p.pushTcpDataToBuffer(*data)
case SOURCE_SERIAL:
go p.pushSerialDataToBuffer(*data)
default:
return errors.New("invalid data source")
}
return nil
}
func (p *pipeline) pushTcpDataToBuffer(data Sensordata) {
time.Sleep(time.Duration(p.tcpDelayMs))
p.tcpMutex.Lock()
p.tcpSensorData = data
p.tcpMutex.Unlock()
}
func (p *pipeline) pushSerialDataToBuffer(data Sensordata) {
time.Sleep(time.Duration(p.serialDelayMs))
p.serialMutex.Lock()
p.serialSensorData = p.serialSensorData.Consolidate(data)
p.serialMutex.Unlock()
}

View File

@ -1,46 +0,0 @@
package dispatcher
import (
"errors"
"fmt"
)
type Dispatcher struct {
listeners map[int16]chan string
counter int16
}
func New() *Dispatcher {
fmt.Println("new dispatcher")
return &Dispatcher{
listeners: make(map[int16]chan string),
counter: 0,
}
}
func (d *Dispatcher) Publish(message string) {
fmt.Println("publish to listeners", len(d.listeners))
for _, ch := range d.listeners {
ch <- message
}
}
func (d *Dispatcher) Subscribe() (id int16, receiver <-chan string) {
fmt.Println("subscribe")
key := d.counter
d.counter++
rec := make(chan string)
d.listeners[key] = rec
return key, rec
}
func (d *Dispatcher) Unsubscribe(id int16) error {
fmt.Println("unsubscribe")
receiver, ok := d.listeners[id]
if !ok {
return errors.New("no subscription with id")
}
delete(d.listeners, id)
close(receiver)
return nil
}

4
go.mod
View File

@ -3,11 +3,9 @@ module git.timovolkmann.de/gyrogpsc
go 1.15
require (
github.com/daedaleanai/ublox v0.0.0-20201103121443-9befa131d32d
github.com/gorilla/websocket v1.4.2
github.com/sparkfun/SparkFun_Ublox_Arduino_Library v1.8.7 // indirect
github.com/m7shapan/njson v1.0.1
github.com/tidwall/pretty v1.0.2
go.bug.st/serial v1.1.1
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf // indirect
golang.org/x/tools v0.0.0-20201121010211-780cb80bd7fb // indirect
)

39
go.sum
View File

@ -1,50 +1,33 @@
github.com/creack/goselect v0.1.1 h1:tiSSgKE1eJtxs1h/VgGQWuXUP0YS4CDIFMp6vaI1ls0=
github.com/creack/goselect v0.1.1/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
github.com/daedaleanai/ublox v0.0.0-20201103121443-9befa131d32d h1:WbFmX8L79E02PgDJYWINhWvceaMGUzgmrwdE5CuUBBk=
github.com/daedaleanai/ublox v0.0.0-20201103121443-9befa131d32d/go.mod h1:pfcwlN8XUYXVYAkPU2LrFZnXIS4EvpZaXh+qRKCN9Sg=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/m7shapan/njson v1.0.1 h1:s+odQrPkzcCCGRTp46cD0XCVYN3pvdoaVwbFVmjAvys=
github.com/m7shapan/njson v1.0.1/go.mod h1:4sidL3oRZO1KV5FkclRBPI7nqFzlIq3BwdxHRMlOa9U=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sparkfun/SparkFun_Ublox_Arduino_Library v1.8.7 h1:T112CHmp+v1bh0W7sp49tZe8SUbw3viSGRTVLziZxfc=
github.com/sparkfun/SparkFun_Ublox_Arduino_Library v1.8.7/go.mod h1:FVoZAzJFrR5D6P8qd2rgpJAV/qF5oODtIT9YjVV+xzY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc=
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.bug.st/serial v1.1.1 h1:5J1DpaIaSIruBi7jVnKXnhRS+YQ9+2PLJMtIZKoIgnc=
go.bug.st/serial v1.1.1/go.mod h1:VmYBeyJWp5BnJ0tw2NUJHZdJTGl2ecBGABHlzRK1knY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf h1:kt3wY1Lu5MJAnKTfoMR52Cu4gwvna4VTzNOiT8tY73s=
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201121010211-780cb80bd7fb h1:z5+u0pkAUPUWd3taoTialQ2JAMo4Wo1Z3L25U4ZV9r0=
golang.org/x/tools v0.0.0-20201121010211-780cb80bd7fb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,132 +0,0 @@
package net
import (
"encoding/json"
"fmt"
"git.timovolkmann.de/gyrogpsc/dispatcher"
"git.timovolkmann.de/gyrogpsc/serial_ubx"
"github.com/gorilla/websocket"
"github.com/tidwall/pretty"
"html/template"
"log"
"net"
"net/http"
"os"
)
func echo(d *dispatcher.Dispatcher) func(w http.ResponseWriter, r *http.Request) {
var upgrader = websocket.Upgrader{} // use default options
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("upgrading to ws")
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
//defer c.Close()
go func() {
for {
if _, _, err := c.NextReader(); err != nil {
c.Close()
break
}
}
}()
dispatcherId, channel := d.Subscribe()
defer d.Unsubscribe(dispatcherId)
for {
log.Println("")
//if err != nil {
// log.Println("read:", err)
// break
//}
cmsg := <-channel
err = c.WriteMessage(websocket.TextMessage, []byte(cmsg))
if err != nil {
log.Println("write:", err)
break
}
}
}
}
func home(w http.ResponseWriter, r *http.Request) {
//var homeTemplate = template.Must(template.New("").ParseFiles("index.html"))
tpl, err := template.ParseFiles("index.html")
if err != nil {
log.Fatalln(err)
}
err = tpl.Execute(w, "ws://"+r.Host+"/echo")
if err != nil {
log.Fatalln(err)
}
}
func NewHttpServer(d *dispatcher.Dispatcher, httpPort string) {
http.HandleFunc("/echo", echo(d))
http.HandleFunc("/", home)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("."))))
log.Fatal(http.ListenAndServe(httpPort, nil))
}
func SerialUbxCollector(d *dispatcher.Dispatcher, serialPort string) {
r, err := serial_ubx.Setup(serialPort)
if err != nil {
log.Fatalln(err)
}
for {
meas, err := r.NextMeasurement()
if err != nil {
continue
}
fmt.Println(meas)
measjson, err := json.Marshal(meas)
d.Publish(string(measjson))
}
}
func TcpJsonCollector(d *dispatcher.Dispatcher, tcpPort string) {
listener, err := net.Listen("tcp", tcpPort)
if err != nil {
fmt.Println("Error listening:", err.Error())
os.Exit(1)
}
// Close the listener when the application closes.
defer listener.Close()
for {
// Listen for an incoming connection.
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}
// Handle connections in a new goroutine.
go handleTcpJsonSensorData(conn, d)
}
}
// Handles incoming requests.
func handleTcpJsonSensorData(conn net.Conn, d *dispatcher.Dispatcher) {
defer conn.Close()
// Make a buffer to hold incoming data.
for {
buf := make([]byte, 2048)
// Read the incoming connection into the buffer.
_, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading:", err.Error())
break
}
json := pretty.Pretty(buf)
fmt.Println(string(json))
d.Publish(string(json))
// Send a response back to person contacting us.
//conn.Write([]byte("success"))
// Close the connection when you're done with it.
}
}

View File

@ -1,124 +0,0 @@
package serial_ubx
import (
"errors"
"fmt"
"git.timovolkmann.de/gyrogpsc/ublox"
"go.bug.st/serial"
"log"
"time"
)
type Measurement struct {
//Timestamp int64 `json:"timestamp"`
Timestamp time.Time `json:"timestamp"`
Position [3]int32 `json:"position"` // Latitude, Longitude, Height
Orientation [3]int32 `json:"orientation"` // Pitch, Roll, Heading
}
type ubxReceiver struct {
decoder *ublox.Decoder
currentMeas Measurement
}
func Setup(portname string) (*ubxReceiver, error) {
mode := &serial.Mode{
BaudRate: 115200,
}
port, err := serial.Open(portname, mode)
if err != nil {
return nil, err
}
return &ubxReceiver{
decoder: ublox.NewDecoder(port),
}, nil
}
func (u *ubxReceiver) Next() (ublox.Message, error) {
return u.decoder.Decode()
}
var (
errNotImplemented = errors.New("message not implemented")
)
// TODO: additional callback with adjustable timing
func (u *ubxReceiver) NextMeasurement() (*Measurement, error) {
msg, err := u.decoder.Decode()
if err != nil {
return nil, err
}
//t := time.Time{}
switch v := msg.(type) {
case *ublox.NavPvt:
t, err := time.Parse(time.RFC3339Nano, formatTime(v.Year_y, v.Month_month, v.Day_d, v.Hour_h, v.Min_min, v.Sec_s, v.Nano_ns))
if err != nil {
log.Println(err)
}
//u.currentMeas.Timestamp = t.UnixNano()
u.currentMeas.Timestamp = t
u.currentMeas.Position[0] = v.Lat_dege7
u.currentMeas.Position[1] = v.Lon_dege7
u.currentMeas.Position[2] = v.Height_mm
fmt.Printf("%T %v\n", *v, *v)
case *ublox.HnrPvt:
t, err := time.Parse(time.RFC3339Nano, formatTime(v.Year_y, v.Month_month, v.Day_d, v.Hour_h, v.Min_min, v.Sec_s, v.Nano_ns))
if err != nil {
log.Println(err)
}
u.currentMeas.Timestamp = t
u.currentMeas.Position[0] = v.Lat_dege7
u.currentMeas.Position[1] = v.Lon_dege7
u.currentMeas.Position[2] = v.Height_mm
fmt.Printf("%T %v\n", *v, *v)
case *ublox.NavAtt:
u.currentMeas.Orientation[0] = v.Pitch_deg
u.currentMeas.Orientation[1] = v.Roll_deg
u.currentMeas.Orientation[2] = v.Heading_deg
fmt.Printf("%T %v\n", *v, *v)
//case *ublox.RawMessage:
// //fmt.Printf("%T %v\n\n", *v, *v)
default:
return nil, errNotImplemented
}
m := u.currentMeas
return &m, nil
}
func formatTime(Year_y uint16, Month_month byte, Day_d byte, Hour_h byte, Min_min byte, Sec_s byte, Nano_ns int32) string {
//Nano_ns *= 1e+3
if Nano_ns < 0 {
Nano_ns += int32(time.Second)
if Sec_s > 0 {
Sec_s--
} else if Min_min > 0 {
Sec_s = 59
Min_min--
} else if Hour_h > 0 {
Sec_s = 59
Min_min = 59
Hour_h--
} else if Day_d > 1 {
Sec_s = 59
Min_min = 59
Hour_h = 23
Day_d--
} // TODO: more cases for exact behavior! good for now...
}
//fmt.Printf("%04d-%02d-%02dT%02d:%02d:%02d.%09dZ00:00\n", Year_y, Month_month, Day_d, Hour_h, Min_min, Sec_s, Nano_ns )
return fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02d.%09dZ", Year_y, Month_month, Day_d, Hour_h, Min_min, Sec_s, Nano_ns)
}
func (u *ubxReceiver) Printloop() {
for {
meas, err := u.NextMeasurement()
if err != nil {
continue
}
fmt.Println(meas)
}
}

View File

@ -63,4 +63,4 @@
-0.006618400104343891
],
"tmd3702_proximity proximity sensor": [5, 0, 0]
}
}

View File

@ -14,17 +14,17 @@ import (
"io"
)
// A Decoder scans an io stream into UBX (0xB5-0x62 separated) or NMEA ("$xxx,,,,*FF\r\n") frames.
// A decoder scans an io stream into UBX (0xB5-0x62 separated) or NMEA ("$xxx,,,,*FF\r\n") frames.
// If you have an unmixed stream of NMEA-only data you can use nmea.Decode() on bufio.Scanner.Bytes() directly.
type Decoder struct {
type decoder struct {
s *bufio.Scanner
}
// NewDecoder creates a new bufio Scanner with a splitfunc that can handle both UBX and NMEA frames.
func NewDecoder(r io.Reader) *Decoder {
func NewDecoder(r io.Reader) *decoder {
d := bufio.NewScanner(r)
d.Split(splitFunc)
return &Decoder{s: d}
return &decoder{s: d}
}
// Assume we're either at the start of an NMEA sentence or at the start of a UBX message
@ -74,8 +74,8 @@ func splitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
return 1 + i1, nil, nil
}
// Decode reads on NMEA or UBX frame and calls DecodeUbx accordingly to parse the message. Skips NMEA.
func (d *Decoder) Decode() (msg Message, err error) {
// Decode reads on NMEA or UBX frame and calls decodeUbx accordingly to parse the message, while skipping NMEA.
func (d *decoder) Decode() (msg interface{}, err error) {
if !d.s.Scan() {
if err = d.s.Err(); err == nil {
err = io.EOF
@ -85,11 +85,10 @@ func (d *Decoder) Decode() (msg Message, err error) {
switch d.s.Bytes()[0] {
case '$':
//fmt.Println("NMEA message: skipping!")
return nil, err
return nil, errors.New("NMEA not implemented")
//return nmea.Decode(d.s.Bytes())
case 0xB5:
return DecodeUbx(d.s.Bytes())
return decodeUbx(d.s.Bytes())
}
panic("impossible frame")
}
@ -99,7 +98,7 @@ var (
errInvalidChkSum = errors.New("invalid UBX checksum")
)
func DecodeUbx(frame []byte) (msg Message, err error) {
func decodeUbx(frame []byte) (msg Message, err error) {
buf := bytes.NewReader(frame)
@ -149,7 +148,7 @@ func DecodeUbx(frame []byte) (msg Message, err error) {
if msg != nil {
err = binary.Read(buf, binary.LittleEndian, msg)
} else {
msg = &RawMessage{ClassID: header.ClassID, Data: append([]byte(nil), frame[6:len(frame)-2]...)}
msg = &RawMessage{classID: header.ClassID, Data: append([]byte(nil), frame[6:len(frame)-2]...)}
}
//fmt.Println(msg)

View File

@ -1,15 +1,21 @@
package ublox
type Message interface {
classID() uint16
ClassID() uint16
}
//type UbxMessage interface {
// Timestamp() (time.Time, error)
// Position() ([3]float64, error)
// Orientation() ([3]float64, error)
//}
type RawMessage struct {
ClassID uint16
classID uint16
Data []byte
}
func (msg *RawMessage) classID() uint16 { return msg.ClassID }
func (msg *RawMessage) ClassID() uint16 { return msg.classID }
type NavPvt struct {
ITOW_ms uint32 // - GPS time of week of the navigation epoch. See the description of iTOW for details.
@ -47,7 +53,7 @@ type NavPvt struct {
MagAcc_deg2e uint16 // 1e-2 Magnetic declination accuracy. Only supported in ADR 4.10 and later.
}
func (NavPvt) classID() uint16 { return 0x0701 }
func (NavPvt) ClassID() uint16 { return 0x0701 }
type HnrPvt struct {
ITOW_ms uint32 // - GPS time of week of the navigation epoch. See the description of iTOW for details.
@ -77,7 +83,7 @@ type HnrPvt struct {
Reserved1 [4]byte // - Reserved
}
func (HnrPvt) classID() uint16 { return 0x0028 }
func (HnrPvt) ClassID() uint16 { return 0x0028 }
type NavAtt struct {
ITOW_ms uint32 // - GPS time of week of the navigation epoch. See the description of iTOW for details.
@ -91,7 +97,7 @@ type NavAtt struct {
AccHeading_deg uint32
}
func (NavAtt) classID() uint16 { return 0x0501 }
func (NavAtt) ClassID() uint16 { return 0x0501 }
//go:generate stringer -output=strings_navpvt.go -trimprefix NavPVT -type=NavPVTFixType,NavPVTValid,NavPVTFlags,NavPVTFlags2,NavPVTFlags3