├── .gitignore
├── Clients
├── CSharpClient
│ └── sharp-arduino-serial-packet-lib
│ │ ├── WpfTester
│ │ ├── App.config
│ │ ├── App.xaml
│ │ ├── App.xaml.cs
│ │ ├── MainWindow.xaml
│ │ ├── MainWindow.xaml.cs
│ │ ├── Properties
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ ├── Resources.resx
│ │ │ ├── Settings.Designer.cs
│ │ │ └── Settings.settings
│ │ └── WpfTester.csproj
│ │ ├── seriallibUnitTests
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ ├── UnitTest1.cs
│ │ └── seriallibUnitTests.csproj
│ │ ├── seriallibtester
│ │ ├── App.config
│ │ ├── Program.cs
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ └── seriallibtester.csproj
│ │ ├── sharp-arduino-serial-packet-lib.gpState
│ │ ├── sharp-arduino-serial-packet-lib.sln
│ │ └── sharp-arduino-serial-packet-lib
│ │ ├── Defaults.cs
│ │ ├── ExtensionsMethods.cs
│ │ ├── HelpStuff.txt
│ │ ├── Packet.cs
│ │ ├── Properties
│ │ └── AssemblyInfo.cs
│ │ ├── SerialPortReaderWriter
│ │ ├── SerialPortManager.cs
│ │ └── SerialSettings.cs
│ │ ├── SerialReaderWriter.cs
│ │ ├── Statistics.cs
│ │ └── sharp-arduino-serial-packet-lib.csproj
├── Collectd
│ ├── KCollectd.png
│ ├── README.md
│ ├── SerialLogger
│ ├── SerialLogger.cpp
│ ├── arduino_distance.log
│ ├── arduino_humidity.log
│ ├── arduino_temperature.log
│ ├── arduinologger_distance.rb
│ ├── arduinologger_humidity.rb
│ ├── arduinologger_temperature.rb
│ ├── collectd.conf
│ └── collectd.png
├── Processing
│ ├── PacketInspector_v1.pde
│ ├── README.md
│ └── ScreenShot.png
└── Python
│ ├── .gitignore
│ ├── README.md
│ ├── makeDebian.sh
│ ├── setup.py
│ └── sp_controller
│ ├── __init__.py
│ ├── __main__.py
│ ├── controller.py
│ ├── infoprinter.py
│ ├── main.py
│ ├── serialcommunication.py
│ ├── serialparser.py
│ ├── settings.py
│ └── tests
│ └── test.py
├── Documentation
├── Doxyfile
└── latex
│ └── refman.pdf
├── LICENSE
├── README.md
└── SerialPacket
├── Protocol.txt
├── SerialPacket.cpp
├── SerialPacket.h
├── build.sh
├── defines.h
├── defines.h.orig
├── examples
├── ArduinoActions
│ ├── ArduinoActions.ino
│ └── SConstruct
├── ReceivePackets
│ ├── ReceivePackets.ino
│ └── SConstruct
├── SendAnalogInput
│ ├── SConstruct
│ └── SendAnalogInput.ino
├── SendPackets
│ ├── SConstruct
│ └── SendPackets.ino
├── SendPacketsOnRequest
│ ├── SConstruct
│ └── SendPacketsOnRequest.ino
└── nose_test.py
├── keywords.txt
└── resources
├── COPYING
├── COPYING.LESSER
├── bcpp_indenter.cfg
├── errors.log
├── lastbuild.log
└── succes.log
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 | *.dylib
9 |
10 | # Compiled Static libraries
11 | *.lai
12 | *.la
13 | *.a
14 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace WpfTester
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Navigation;
15 | using System.Windows.Shapes;
16 | using System.Windows.Threading;
17 | using sharp_arduino_serial_packet_lib;
18 |
19 | namespace WpfTester
20 | {
21 | ///
22 | /// Interaction logic for MainWindow.xaml
23 | ///
24 | public partial class MainWindow : Window
25 | {
26 | public MainWindow()
27 | {
28 | InitializeComponent();
29 | wr = new SerialReaderWriter(comport: "COM4");
30 | }
31 |
32 | private SerialReaderWriter wr;
33 | private bool listening = false;
34 | private void btnStartListening_Click(object sender, RoutedEventArgs e)
35 | {
36 | if (listening == false)
37 | {
38 | wr.SerialMessageReceived += wr_SerialMessageReceived;
39 | wr.StartListening();
40 | listening = true;
41 | btnStartListening.Content = "Stop listening";
42 | }
43 | else
44 | {
45 | wr.SerialMessageReceived -= wr_SerialMessageReceived;
46 | wr.StopListening();
47 | listening = false;
48 | btnStartListening.Content = "Start listening";
49 | }
50 |
51 | }
52 |
53 | private delegate void UpdateUiTextDelegate(Packet recPacket);
54 | void wr_SerialMessageReceived(object sender, SerialArduinoMessageEventArgs e)
55 | {
56 | Dispatcher.Invoke(
57 | DispatcherPriority.Send,
58 | new Action(
59 | () =>
60 | {
61 | lbPackets.Items.Insert(0, e.Packet);
62 | }
63 | )
64 | );
65 |
66 | }
67 |
68 | }
69 |
70 | public class CommandToText : IValueConverter
71 | {
72 | public object Convert(object value, Type targetType,
73 | object parameter, CultureInfo culture)
74 | {
75 | var incCom = (Commands)value;
76 |
77 | return incCom.ToString();
78 | }
79 |
80 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
81 | {
82 | throw new NotImplementedException();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("WpfTester")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("WpfTester")]
15 | [assembly: AssemblyCopyright("Copyright © 2013")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18033
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace WpfTester.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WpfTester.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18033
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace WpfTester.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/WpfTester/WpfTester.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6F1EE2D0-22A6-4F88-8BB1-D3A52FCCC921}
8 | WinExe
9 | Properties
10 | WpfTester
11 | WpfTester
12 | v4.5
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 4.0
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | MSBuild:Compile
54 | Designer
55 |
56 |
57 | MSBuild:Compile
58 | Designer
59 |
60 |
61 | App.xaml
62 | Code
63 |
64 |
65 | MainWindow.xaml
66 | Code
67 |
68 |
69 |
70 |
71 | Code
72 |
73 |
74 | True
75 | True
76 | Resources.resx
77 |
78 |
79 | True
80 | Settings.settings
81 | True
82 |
83 |
84 | ResXFileCodeGenerator
85 | Resources.Designer.cs
86 |
87 |
88 | SettingsSingleFileGenerator
89 | Settings.Designer.cs
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | {57d2e5ba-3b0b-4a73-8ae6-c19f1fd493fb}
99 | sharp-arduino-serial-packet-lib
100 |
101 |
102 |
103 |
110 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibUnitTests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("seriallibUnitTests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("seriallibUnitTests")]
13 | [assembly: AssemblyCopyright("Copyright © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("3b54f0eb-dd3e-47df-a73f-be555f10a3ec")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibUnitTests/UnitTest1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using sharp_arduino_serial_packet_lib;
4 | using sharp_arduino_serial_packet_lib.SerialPortReaderWriter;
5 |
6 | namespace seriallibUnitTests
7 | {
8 | //More info: http://msdn.microsoft.com/en-us/library/hh694602.aspx
9 | [TestClass]
10 | public class PacketParsingTest
11 | {
12 | [TestMethod]
13 | public void SendPacketTest()
14 | {
15 | SerialReaderWriter rw = new SerialReaderWriter(new SerialSettings());
16 | rw.ParseData("T01N01I00P32Q00");
17 |
18 | Packet p = new Packet();
19 | p.PacketType = (PacketTypes)"01".FromHexStringToInt();
20 |
21 | p.NodeID = "01".FromHexStringToInt();
22 | p.CommandID = (Commands)"40".FromHexStringToInt();
23 | p.Payload = "32".FromHexStringToInt();
24 | p.Parity = "00".FromHexStringToInt();
25 |
26 |
27 | Assert.AreEqual(rw.incomingPacket, p);
28 |
29 | //TODO: expand test (test other fields, test with more strings)
30 |
31 | }
32 | //TODO: test other methods (if we are bored some day :) )
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibUnitTests/seriallibUnitTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {2D51C53E-8AE0-44F1-954F-07C4B1CD9272}
7 | Library
8 | Properties
9 | seriallibUnitTests
10 | seriallibUnitTests
11 | v4.5
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | ExtensionsMethods.cs
55 |
56 |
57 |
58 |
59 |
60 |
61 | {57d2e5ba-3b0b-4a73-8ae6-c19f1fd493fb}
62 | sharp-arduino-serial-packet-lib
63 |
64 |
65 |
66 |
67 |
68 |
69 | False
70 |
71 |
72 | False
73 |
74 |
75 | False
76 |
77 |
78 | False
79 |
80 |
81 |
82 |
83 |
84 |
85 |
92 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibtester/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibtester/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using sharp_arduino_serial_packet_lib;
3 |
4 | namespace seriallibtester
5 | {
6 | class Program
7 | {
8 | private static SerialReaderWriter r;
9 | static void Main(string[] args)
10 | {
11 | try
12 | {
13 | r = new SerialReaderWriter(comport: "COM4");
14 | r.SerialMessageReceived += r_SerialDataReceived;
15 | r.StartListening();
16 | while (true)
17 | {
18 |
19 | }
20 | }
21 | catch (Exception e)
22 | {
23 | Console.WriteLine(e.Message);
24 | }
25 | }
26 |
27 | static void r_SerialDataReceived(object sender, SerialArduinoMessageEventArgs e)
28 | {
29 |
30 | Console.WriteLine(e.Packet.ToString());
31 | Console.WriteLine("Received:{0} Corrupt: {1}",r.Statistics.ReceivedPackets, r.Statistics.CorruptPackets);
32 |
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibtester/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("seriallibtester")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("seriallibtester")]
13 | [assembly: AssemblyCopyright("Copyright © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("247c0880-8d21-41e1-a557-c344c353fc5a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/seriallibtester/seriallibtester.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A104ABD2-5D4A-423B-9467-D902C0AB56C6}
8 | Exe
9 | Properties
10 | seriallibtester
11 | seriallibtester
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | AllRules.ruleset
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | {57d2e5ba-3b0b-4a73-8ae6-c19f1fd493fb}
54 | sharp-arduino-serial-packet-lib
55 |
56 |
57 |
58 |
65 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib.gpState:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharp-arduino-serial-packet-lib", "sharp-arduino-serial-packet-lib\sharp-arduino-serial-packet-lib.csproj", "{57D2E5BA-3B0B-4A73-8AE6-C19F1FD493FB}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "seriallibtester", "seriallibtester\seriallibtester.csproj", "{A104ABD2-5D4A-423B-9467-D902C0AB56C6}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfTester", "WpfTester\WpfTester.csproj", "{6F1EE2D0-22A6-4F88-8BB1-D3A52FCCC921}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "seriallibUnitTests", "seriallibUnitTests\seriallibUnitTests.csproj", "{2D51C53E-8AE0-44F1-954F-07C4B1CD9272}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {57D2E5BA-3B0B-4A73-8AE6-C19F1FD493FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {57D2E5BA-3B0B-4A73-8AE6-C19F1FD493FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {57D2E5BA-3B0B-4A73-8AE6-C19F1FD493FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {57D2E5BA-3B0B-4A73-8AE6-C19F1FD493FB}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {A104ABD2-5D4A-423B-9467-D902C0AB56C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {A104ABD2-5D4A-423B-9467-D902C0AB56C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {A104ABD2-5D4A-423B-9467-D902C0AB56C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {A104ABD2-5D4A-423B-9467-D902C0AB56C6}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {6F1EE2D0-22A6-4F88-8BB1-D3A52FCCC921}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {6F1EE2D0-22A6-4F88-8BB1-D3A52FCCC921}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {6F1EE2D0-22A6-4F88-8BB1-D3A52FCCC921}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {6F1EE2D0-22A6-4F88-8BB1-D3A52FCCC921}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {2D51C53E-8AE0-44F1-954F-07C4B1CD9272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {2D51C53E-8AE0-44F1-954F-07C4B1CD9272}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {2D51C53E-8AE0-44F1-954F-07C4B1CD9272}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {2D51C53E-8AE0-44F1-954F-07C4B1CD9272}.Release|Any CPU.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/Defaults.cs:
--------------------------------------------------------------------------------
1 | namespace sharp_arduino_serial_packet_lib
2 | {
3 | //http://www.codeproject.com/Articles/75770/Basic-serial-port-listening-application
4 | public class Defaults
5 | {
6 | public const int DEFAULT_BAUDRATE = 115200;
7 | }
8 | public enum SensorTypes
9 | {
10 |
11 | TEMPERATURE = 0x10,
12 | HUMIDITY = 0x11,
13 | DISTANCE = 0x30,
14 | MOTORSTATUS = 0x50
15 | }
16 | public enum Commands
17 | {
18 | STOP_MOTOR_A = 0x10,
19 | START_MOTOR_A = 0x11,
20 | SET_SPEED_MOTOR_A = 0x12,
21 | BRAKE_MOTOR_A = 0x13,
22 | STOP_MOTOR_B = 0x15,
23 | START_MOTOR_B = 0x16,
24 | SET_SPEED_MOTOR_B = 0x17,
25 | BRAKE_MOTOR_B = 0x18
26 | }
27 | public enum PacketFields { Type, NodeID, SensorID, CommandID, Payload, Parity }
28 | public enum PacketTypes { Command = 0x01, Command_Reply = 0x02, Data_Request = 0x11, Data_Byte = 0x12, Data_Int = 0x13, Data_Array_Request = 0x21, Data_Array = 0x22 }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/ExtensionsMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace sharp_arduino_serial_packet_lib
4 | {
5 | static class ExtensionsMethods
6 | {
7 |
8 | public static int FromHexStringToInt(this string hexstr)
9 | {
10 | if (hexstr.Length == 2)
11 | {
12 | return Convert.ToInt32(hexstr, 16);
13 | }
14 | throw new IndexOutOfRangeException("Can only create int from 2-length hex arrays. String received: " + hexstr);
15 | }
16 |
17 | public static string FromIntToHexString(this int hexstr)
18 | {
19 | //TODO
20 | throw new NotImplementedException();
21 | }
22 |
23 | public static T[] SubArray(this T[] data, int index, int length)
24 | {
25 | var result = new T[length];
26 | Array.Copy(data, index, result, 0, length);
27 | return result;
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/HelpStuff.txt:
--------------------------------------------------------------------------------
1 | http://stackoverflow.com/questions/10501376/thread-safe-buffer-for-net
2 |
3 | DOEN! http://stackoverflow.com/questions/8286503/c-sharp-how-to-place-serial-input-data-into-a-queue-and-de-que-using-a-backgroun
4 |
5 | http://stackoverflow.com/questions/7687379/c-sharp-usb-parsing-of-a-urb-bulk-or-interrupt-transfer-packet
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/Packet.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace sharp_arduino_serial_packet_lib
4 | {
5 |
6 | public class Packet
7 | {
8 | public PacketTypes PacketType { get; set; }
9 | public int NodeID { get; set; }
10 | public int SensorID { get; set; }
11 | public Commands CommandID { get; set; }
12 | public int Payload { get; set; }
13 | public int Parity { get; set; }
14 |
15 | public string RawString { get; set; }
16 | public override string ToString()
17 | {
18 | return string.Format("Raw string:{6} \nType:{0} " +
19 | "Node:{1} " +
20 | "Sensor:{2} Command: {3}"+
21 | "Payload:{4} Parity:{5}\n",PacketType,NodeID,SensorID,CommandID,Payload, Parity, RawString.Trim());
22 |
23 | }
24 |
25 | public override bool Equals(object obj)
26 | {
27 | Packet inco = obj as Packet;
28 | if (inco != null)
29 | {
30 | if (inco.Parity == this.Parity)
31 | {
32 | if (inco.NodeID == this.NodeID && inco.PacketType == this.PacketType && inco.Payload == this.Payload &&
33 | inco.SensorID == this.SensorID)
34 | return true;
35 | }
36 | }
37 | return false;
38 | }
39 |
40 | public string ToStringMessageArray()
41 | {
42 | StringBuilder res = new StringBuilder();
43 | res.Append('T');
44 | int type = (int) this.PacketType;
45 | res.Append(type.FromIntToHexString()); //TODO: make this more straightforward/faster
46 | res.Append('N');
47 | res.Append(NodeID.FromIntToHexString());
48 | res.Append('I');
49 | if (this.PacketType == PacketTypes.Command || this.PacketType == PacketTypes.Command_Reply)
50 | {
51 | int com = (int) this.CommandID;
52 | res.Append(com.FromIntToHexString());
53 | }
54 | else res.Append(this.SensorID.FromIntToHexString());
55 | res.Append('P');
56 | res.Append(this.Payload.FromIntToHexString());
57 | res.Append('Q');
58 | res.Append(this.Parity);
59 | return res.ToString();
60 |
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("sharp-arduino-serial-packet-lib")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("Artesis")]
11 | [assembly: AssemblyProduct("sharp-arduino-serial-packet-lib")]
12 | [assembly: AssemblyCopyright("Artesis © 2013")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("f4df84f4-db75-43f3-897b-7890b07100e3")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/SerialPortReaderWriter/SerialPortManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO.Ports;
3 | using System.Reflection;
4 |
5 | namespace sharp_arduino_serial_packet_lib.SerialPortReaderWriter
6 | {
7 | ///
8 | /// Manager for serial port data
9 | ///
10 | //Original source: http://www.codeproject.com/Articles/75770/Basic-serial-port-listening-application
11 | class SerialPortManager : IDisposable
12 | {
13 | public SerialPortManager()
14 | {
15 | // Finding installed serial ports on hardware
16 | _currentSerialSettings.PortNameCollection = SerialPort.GetPortNames();
17 | _currentSerialSettings.PropertyChanged += _currentSerialSettings_PropertyChanged;
18 |
19 | // If serial ports is found, we select the first found
20 | if (_currentSerialSettings.PortNameCollection.Length > 0)
21 | _currentSerialSettings.PortName = _currentSerialSettings.PortNameCollection[0];
22 | }
23 |
24 |
25 | ~SerialPortManager()
26 | {
27 | Dispose(false);
28 | }
29 |
30 |
31 | #region Fields
32 | private SerialPort _serialPort;
33 | private SerialSettings _currentSerialSettings = new SerialSettings();
34 | public event EventHandler NewSerialDataReceived;
35 |
36 | #endregion
37 |
38 | #region Properties
39 | ///
40 | /// Gets or sets the current serial port settings
41 | ///
42 | public SerialSettings CurrentSerialSettings
43 | {
44 | get { return _currentSerialSettings; }
45 | set { _currentSerialSettings = value; }
46 | }
47 |
48 | #endregion
49 |
50 | #region Event handlers
51 |
52 | void _currentSerialSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
53 | {
54 | // if serial port is changed, a new baud query is issued
55 | if (e.PropertyName.Equals("PortName"))
56 | UpdateBaudRateCollection();
57 | }
58 |
59 |
60 | void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
61 | {
62 | string nbrDataRead = _serialPort.ReadLine();
63 | if (nbrDataRead.Length == 0)
64 | return;
65 |
66 | // Send data to whom ever interested
67 | if (NewSerialDataReceived != null)
68 | NewSerialDataReceived(this, new SerialDataEventArgs(nbrDataRead));
69 | }
70 |
71 | #endregion
72 |
73 | #region Methods
74 |
75 | ///
76 | /// Connects to a serial port defined through the current settings
77 | ///
78 | public void StartUsingPort()
79 | {
80 | // Closing serial port if it is open
81 | if (_serialPort != null && _serialPort.IsOpen)
82 | _serialPort.Close();
83 |
84 | // Setting serial port settings
85 | _serialPort = new SerialPort(
86 | _currentSerialSettings.PortName,
87 | _currentSerialSettings.BaudRate,
88 | _currentSerialSettings.Parity,
89 | _currentSerialSettings.DataBits,
90 | _currentSerialSettings.StopBits);
91 |
92 | // Subscribe to event and open serial port for data
93 | _serialPort.DataReceived += _serialPort_DataReceived;
94 | _serialPort.Open();
95 | }
96 |
97 | ///
98 | /// Closes the serial port
99 | ///
100 | public void StopUsingPort()
101 | {
102 | _serialPort.Close();
103 | }
104 |
105 | ///
106 | /// Send serial byte array to serialport
107 | ///
108 | ///
109 | public void SendSerialData(string data)
110 | {
111 | if (_serialPort != null && _serialPort.IsOpen)
112 | {
113 | _serialPort.WriteLine(data);
114 | //TODO: http://www.ibiliskov.info/2011/05/net-serialport-pitfalls/
115 | }
116 | else
117 | {
118 | throw new Exception("No serial port open. Did you call the StartUsingPort method?");
119 | }
120 | }
121 |
122 |
123 | ///
124 | /// Retrieves the current selected device's COMMPROP structure, and extracts the dwSettableBaud property
125 | ///
126 | private void UpdateBaudRateCollection()
127 | {
128 | _serialPort = new SerialPort(_currentSerialSettings.PortName);
129 | _serialPort.Open();
130 | var field = _serialPort.BaseStream.GetType().GetField("commProp", BindingFlags.Instance | BindingFlags.NonPublic);
131 | if (field != null)
132 | {
133 | var p = field.GetValue(_serialPort.BaseStream);
134 |
135 | if (p != null)
136 | {
137 | var fieldInfo = p.GetType().GetField("dwSettableBaud", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
138 | if (fieldInfo != null)
139 | {
140 | var dwSettableBaud = (Int32)fieldInfo.GetValue(p);
141 |
142 | _serialPort.Close();
143 | _currentSerialSettings.UpdateBaudRateCollection(dwSettableBaud);
144 | }
145 | }
146 |
147 | }
148 | }
149 |
150 | // Call to release serial port
151 | public void Dispose()
152 | {
153 | Dispose(true);
154 | }
155 |
156 | // Part of basic design pattern for implementing Dispose
157 | protected virtual void Dispose(bool disposing)
158 | {
159 | if (disposing)
160 | {
161 | _serialPort.DataReceived -= _serialPort_DataReceived;
162 | }
163 | // Releasing serial port (and other unmanaged objects)
164 | if (_serialPort != null)
165 | {
166 | if (_serialPort.IsOpen)
167 | _serialPort.Close();
168 |
169 | _serialPort.Dispose();
170 | }
171 | }
172 |
173 |
174 | #endregion
175 |
176 | }
177 |
178 | ///
179 | /// EventArgs used to send bytes received on serial port
180 | ///
181 | public class SerialDataEventArgs : EventArgs
182 | {
183 | public SerialDataEventArgs(string dataInByteArray)
184 | {
185 | Data = dataInByteArray;
186 | }
187 |
188 | ///
189 | /// Byte array containing data from serial port
190 | ///
191 | public string Data;
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/SerialPortReaderWriter/SerialSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.IO.Ports;
4 |
5 | namespace sharp_arduino_serial_packet_lib.SerialPortReaderWriter
6 | {
7 |
8 | ///
9 | /// Class containing properties related to a serial port
10 | ///
11 | //Original source: http://www.codeproject.com/Articles/75770/Basic-serial-port-listening-application
12 | public class SerialSettings : INotifyPropertyChanged
13 | {
14 | public event PropertyChangedEventHandler PropertyChanged;
15 | string _portName = "";
16 | int _baudRate = 115200;
17 | readonly BindingList _baudRateCollection = new BindingList();
18 | Parity _parity = Parity.None;
19 | int _dataBits = 8;
20 | int[] _dataBitsCollection = { 5, 6, 7, 8 };
21 | StopBits _stopBits = StopBits.One;
22 |
23 | #region Properties
24 | ///
25 | /// The port to use (for example, COM1).
26 | ///
27 | public string PortName
28 | {
29 | get { return _portName; }
30 | set
31 | {
32 | if (!_portName.Equals(value))
33 | {
34 | _portName = value;
35 | SendPropertyChangedEvent("PortName");
36 | }
37 | }
38 | }
39 | ///
40 | /// The baud rate.
41 | ///
42 | public int BaudRate
43 | {
44 | get { return _baudRate; }
45 | set
46 | {
47 | if (_baudRate != value)
48 | {
49 | _baudRate = value;
50 | SendPropertyChangedEvent("BaudRate");
51 | }
52 | }
53 | }
54 |
55 | ///
56 | /// One of the Parity values.
57 | ///
58 | public Parity Parity
59 | {
60 | get { return _parity; }
61 | set
62 | {
63 | if (_parity != value)
64 | {
65 | _parity = value;
66 | SendPropertyChangedEvent("Parity");
67 | }
68 | }
69 | }
70 | ///
71 | /// The data bits value.
72 | ///
73 | public int DataBits
74 | {
75 | get { return _dataBits; }
76 | set
77 | {
78 | if (_dataBits != value)
79 | {
80 | _dataBits = value;
81 | SendPropertyChangedEvent("DataBits");
82 | }
83 | }
84 | }
85 | ///
86 | /// One of the StopBits values.
87 | ///
88 | public StopBits StopBits
89 | {
90 | get { return _stopBits; }
91 | set
92 | {
93 | if (_stopBits != value)
94 | {
95 | _stopBits = value;
96 | SendPropertyChangedEvent("StopBits");
97 | }
98 | }
99 | }
100 |
101 | ///
102 | /// Available ports on the computer
103 | ///
104 | public string[] PortNameCollection { get; set; }
105 |
106 | ///
107 | /// Available baud rates for current serial port
108 | ///
109 | public BindingList BaudRateCollection
110 | {
111 | get { return _baudRateCollection; }
112 | }
113 |
114 | ///
115 | /// Available databits setting
116 | ///
117 | public int[] DataBitsCollection
118 | {
119 | get { return _dataBitsCollection; }
120 | set { _dataBitsCollection = value; }
121 | }
122 |
123 | #endregion
124 |
125 | #region Methods
126 | ///
127 | /// Updates the range of possible baud rates for device
128 | ///
129 | /// dwSettableBaud parameter from the COMMPROP Structure
130 | /// An updated list of values
131 | public void UpdateBaudRateCollection(int possibleBaudRates)
132 | {
133 | const int BAUD_075 = 0x00000001;
134 | const int BAUD_110 = 0x00000002;
135 | const int BAUD_150 = 0x00000008;
136 | const int BAUD_300 = 0x00000010;
137 | const int BAUD_600 = 0x00000020;
138 | const int BAUD_1200 = 0x00000040;
139 | const int BAUD_1800 = 0x00000080;
140 | const int BAUD_2400 = 0x00000100;
141 | const int BAUD_4800 = 0x00000200;
142 | const int BAUD_7200 = 0x00000400;
143 | const int BAUD_9600 = 0x00000800;
144 | const int BAUD_14400 = 0x00001000;
145 | const int BAUD_19200 = 0x00002000;
146 | const int BAUD_38400 = 0x00004000;
147 | const int BAUD_56K = 0x00008000;
148 | const int BAUD_57600 = 0x00040000;
149 | const int BAUD_115200 = 0x00020000;
150 | const int BAUD_128K = 0x00010000;
151 |
152 | _baudRateCollection.Clear();
153 |
154 | if ((possibleBaudRates & BAUD_075) > 0)
155 | _baudRateCollection.Add(75);
156 | if ((possibleBaudRates & BAUD_110) > 0)
157 | _baudRateCollection.Add(110);
158 | if ((possibleBaudRates & BAUD_150) > 0)
159 | _baudRateCollection.Add(150);
160 | if ((possibleBaudRates & BAUD_300) > 0)
161 | _baudRateCollection.Add(300);
162 | if ((possibleBaudRates & BAUD_600) > 0)
163 | _baudRateCollection.Add(600);
164 | if ((possibleBaudRates & BAUD_1200) > 0)
165 | _baudRateCollection.Add(1200);
166 | if ((possibleBaudRates & BAUD_1800) > 0)
167 | _baudRateCollection.Add(1800);
168 | if ((possibleBaudRates & BAUD_2400) > 0)
169 | _baudRateCollection.Add(2400);
170 | if ((possibleBaudRates & BAUD_4800) > 0)
171 | _baudRateCollection.Add(4800);
172 | if ((possibleBaudRates & BAUD_7200) > 0)
173 | _baudRateCollection.Add(7200);
174 | if ((possibleBaudRates & BAUD_9600) > 0)
175 | _baudRateCollection.Add(9600);
176 | if ((possibleBaudRates & BAUD_14400) > 0)
177 | _baudRateCollection.Add(14400);
178 | if ((possibleBaudRates & BAUD_19200) > 0)
179 | _baudRateCollection.Add(19200);
180 | if ((possibleBaudRates & BAUD_38400) > 0)
181 | _baudRateCollection.Add(38400);
182 | if ((possibleBaudRates & BAUD_56K) > 0)
183 | _baudRateCollection.Add(56000);
184 | if ((possibleBaudRates & BAUD_57600) > 0)
185 | _baudRateCollection.Add(57600);
186 | if ((possibleBaudRates & BAUD_115200) > 0)
187 | _baudRateCollection.Add(115200);
188 | if ((possibleBaudRates & BAUD_128K) > 0)
189 | _baudRateCollection.Add(128000);
190 |
191 | SendPropertyChangedEvent("BaudRateCollection");
192 | }
193 |
194 | ///
195 | /// Send a PropertyChanged event
196 | ///
197 | /// Name of changed property
198 | private void SendPropertyChangedEvent(String propertyName)
199 | {
200 | if (PropertyChanged != null)
201 | PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
202 | }
203 |
204 | #endregion
205 | }
206 |
207 |
208 | }
209 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/SerialReaderWriter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using sharp_arduino_serial_packet_lib.SerialPortReaderWriter;
4 |
5 | namespace sharp_arduino_serial_packet_lib
6 | {
7 | public class SerialReaderWriter : IDisposable
8 | {
9 |
10 | public SerialSettings SerialSettings
11 | {
12 | get { return spManager.CurrentSerialSettings; }
13 | set { spManager.CurrentSerialSettings = value; }
14 | }
15 | public Statistics Statistics
16 | {
17 | get { return _statistics; }
18 | }
19 |
20 |
21 |
22 | #region Constructors
23 | public SerialReaderWriter(int baudrate = 115200, string comport = "COM2")
24 | {
25 | _statistics = new Statistics();
26 | spManager.CurrentSerialSettings.BaudRate = baudrate;
27 | spManager.CurrentSerialSettings.PortName = comport;
28 | }
29 |
30 | public SerialReaderWriter(SerialSettings settings)
31 | {
32 | _statistics = new Statistics();
33 | spManager.CurrentSerialSettings = settings;
34 | }
35 |
36 | private readonly SerialPortManager spManager = new SerialPortManager();
37 | #endregion
38 |
39 | private int ComputeParity()
40 | {
41 | //TODO: compute parity (ask Jeroen)
42 | return incomingPacket.Parity;
43 | }
44 |
45 | #region Receiving methods
46 |
47 | public void StartListening()
48 | {
49 | if (spManager != null)
50 | {
51 | spManager.NewSerialDataReceived += OnNewSerialDataReceived;
52 | spManager.StartUsingPort();
53 | }
54 |
55 | }
56 | public void StopListening()
57 | {
58 | if (spManager != null)
59 | {
60 | spManager.NewSerialDataReceived -= OnNewSerialDataReceived;
61 | spManager.StopUsingPort();
62 | }
63 | }
64 |
65 | private readonly Statistics _statistics;
66 | void OnNewSerialDataReceived(object sender, SerialDataEventArgs e)
67 | {
68 | Statistics.ReceivedPackets++;
69 |
70 | try
71 | {
72 | ParseData(e.Data);
73 | }
74 | catch (Exception)
75 | {
76 | Debug.WriteLine("Corrupt packet: dropped + (" + (e.Data) + ")");
77 | Statistics.CorruptPackets++;
78 | }
79 |
80 | }
81 | public event EventHandler SerialMessageReceived;
82 |
83 |
84 |
85 | public Packet incomingPacket = new Packet();
86 | private PacketFields currentField;
87 | public void ParseData(string packetStr)
88 | {
89 |
90 | Debug.WriteLine("New packet:\t string:" + packetStr);
91 |
92 | for (int i = 0; i < packetStr.Length; i++)
93 | {
94 | //Simple state-machine
95 | if (packetStr[i] == 'T')
96 | {
97 | incomingPacket = new Packet { RawString = packetStr };
98 | currentField = PacketFields.Type;
99 | }
100 |
101 | else if (packetStr[i] == 'N')
102 | currentField = PacketFields.NodeID;
103 | else if (packetStr[i] == 'I')
104 | {
105 | if (incomingPacket.PacketType == PacketTypes.Command || incomingPacket.PacketType == PacketTypes.Command_Reply)
106 | currentField = PacketFields.CommandID;
107 | else if (incomingPacket.PacketType == PacketTypes.Data_Array_Request || incomingPacket.PacketType == PacketTypes.Data_Int || incomingPacket.PacketType == PacketTypes.Data_Request)
108 | {
109 | currentField = PacketFields.SensorID;
110 | }
111 | }
112 | else if (packetStr[i] == 'P')
113 | currentField = PacketFields.Payload;
114 | else if (packetStr[i] == 'Q')
115 | currentField = PacketFields.Parity;
116 | else
117 | {
118 | switch (currentField)
119 | {
120 | case PacketFields.Type:
121 | incomingPacket.PacketType = (PacketTypes)packetStr.Substring(i, 2).FromHexStringToInt();
122 | i++;
123 | break;
124 | case PacketFields.NodeID:
125 | incomingPacket.NodeID = packetStr.Substring(i, 2).FromHexStringToInt();
126 | i++;
127 | break;
128 | case PacketFields.SensorID:
129 | incomingPacket.SensorID = packetStr.Substring(i, 2).FromHexStringToInt();
130 | i++;
131 | break;
132 | case PacketFields.CommandID:
133 | incomingPacket.CommandID = (Commands)packetStr.Substring(i, 2).FromHexStringToInt();
134 | i++;
135 | break;
136 | case PacketFields.Payload:
137 | incomingPacket.Payload = packetStr.Substring(i, 2).FromHexStringToInt();
138 | i++;
139 | break;
140 | case PacketFields.Parity:
141 | incomingPacket.Parity = packetStr.Substring(i, 2).FromHexStringToInt();
142 | i = packetStr.Length; //we're done with this packet
143 |
144 | if (SerialMessageReceived != null && ComputeParity() == incomingPacket.Parity) //&& parity klopt
145 | SerialMessageReceived(this, new SerialArduinoMessageEventArgs(incomingPacket));
146 | else
147 | {
148 | Debug.WriteLine("Parity failed");
149 | }
150 | break;
151 | default:
152 | throw new ArgumentOutOfRangeException();
153 | }
154 | }
155 |
156 | }
157 |
158 | }
159 | #endregion
160 |
161 | #region Send methods
162 |
163 | public void SendPacket(PacketTypes ptype, int nodeId, int sensorID, Commands command, int payload)
164 | {
165 | Packet res= new Packet();
166 | res.PacketType = ptype;
167 | res.NodeID = nodeId;
168 | res.SensorID = sensorID;
169 | res.CommandID = command;
170 | res.Payload = payload;
171 | res.Parity = ComputeParity(); //TODO
172 |
173 | spManager.SendSerialData(res.ToStringMessageArray());
174 |
175 | }
176 | #endregion
177 |
178 | #region Dispose
179 | protected virtual void Dispose(bool disposing)
180 | {
181 | if (disposing)
182 | {
183 | spManager.StopUsingPort();
184 | spManager.NewSerialDataReceived -= OnNewSerialDataReceived;
185 | spManager.Dispose();
186 | }
187 |
188 | }
189 | public void Dispose()
190 | {
191 | Dispose(true);
192 | GC.SuppressFinalize(this);
193 | }
194 | #endregion
195 |
196 |
197 | }
198 | public class SerialArduinoMessageEventArgs : EventArgs
199 | {
200 | public Packet Packet { get; set; }
201 |
202 | public SerialArduinoMessageEventArgs(Packet pckt)
203 | {
204 | Packet = pckt;
205 | }
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/Statistics.cs:
--------------------------------------------------------------------------------
1 | namespace sharp_arduino_serial_packet_lib
2 | {
3 | public class Statistics
4 | {
5 | public int ReceivedPackets { get; set; }
6 | public int CorruptPackets { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/Clients/CSharpClient/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib/sharp-arduino-serial-packet-lib.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {57D2E5BA-3B0B-4A73-8AE6-C19F1FD493FB}
8 | Library
9 | Properties
10 | sharp_arduino_serial_packet_lib
11 | sharp-arduino-serial-packet-lib
12 | v3.5
13 | 512
14 | Client
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | false
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | false
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
64 |
--------------------------------------------------------------------------------
/Clients/Collectd/KCollectd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeroendoggen/Arduino-serial-messaging/87bdc590bfb85e6d31165f1c8e87f0d09042c8cc/Clients/Collectd/KCollectd.png
--------------------------------------------------------------------------------
/Clients/Collectd/README.md:
--------------------------------------------------------------------------------
1 | ## Arduino sensor logging with collectd & RRDtool
2 |
3 | Save Arduino sensor readings in a RRDtool database using 'collectd'.
4 |
5 | Program flow:
6 |
7 | 1. The Arduino reads its sensors.
8 | 2. The Arduino sends a serial data packet to the 'server'.
9 | 3. The server runs a c++ application to listen for serial packets.
10 | 4. The server writes the payloads of the incoming packets to logfiles.
11 | 5. Every 'x' seconds, the 'collectd' daemon runs a Ruby script to read the data from the logfiles.
12 | 6. You can inspect, monitor, graph the info with any RRDtool compatible application. (e.g. Cacti, Nagios, KCollectd)
13 |
14 | ## KCollectd Screenshots
15 |
16 | KCollectd is a RRDtool graphing frontend for KDE.
17 |
18 | Screenhot shows: (sensing interval: 10 seconds)
19 |
20 | * Orange line: CPU usage
21 | * Green line: temperature sensor data (fake data: 'up/down counter')
22 | * Blue line: distance sensor data (fake data: 'up/down counter x 2')
23 | * Pink line: humidity sensor data (fake data: 'up/down counter + 100')
24 |
25 | 
26 |
27 | ## Links
28 |
29 | * [RRDtool](http://oss.oetiker.ch/rrdtool/): Industry standard, high performance data logging and graphing system for time series data.
30 | * [Nagios](http://www.nagios.org/): IT Infrastructure Monitoring
31 | * [KCollectd](http://www.forwiss.uni-passau.de/~berberic/Linux/kcollectd.html): a KDE-based application for displaying RRD data collected by collectd
32 | * [writing collectd plugins](http://support.rightscale.com/12-Guides/RightScale_101/08-Management_Tools/Monitoring_System/Writing_custom_collectd_plugins/Custom_Collectd_Plug-ins_for_Linux)
--------------------------------------------------------------------------------
/Clients/Collectd/SerialLogger:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeroendoggen/Arduino-serial-messaging/87bdc590bfb85e6d31165f1c8e87f0d09042c8cc/Clients/Collectd/SerialLogger
--------------------------------------------------------------------------------
/Clients/Collectd/SerialLogger.cpp:
--------------------------------------------------------------------------------
1 | // SerialLogger.cpp - Read 'serialPacket' data and write logfiles for collectd
2 | // Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
3 | // More info:
4 | //
5 | // Version History:
6 | // Version 0.0.1: Just a first quick and dirty first implementation !!
7 | //
8 | // This program is free software; you can redistribute it and/or
9 | // modify it under the terms of the GNU Lesser General Public
10 | // License as published by the Free Software Foundation; either
11 | // version 2.1 of the License, or (at your option) any later version.
12 | //
13 | // This program is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 | // Lesser General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU Lesser General Public
19 | // License along with this program; if not, write to the Free Software
20 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 |
22 |
23 | // TODO list:
24 | /// @todo:
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #define TEMPERATURE 0x10
33 | #define HUMIDITY 0x11
34 | #define DISTANCE 0x30
35 |
36 | int hex_to_dec(int in);
37 |
38 | int main( int argc, char** argv )
39 | {
40 | //
41 | // Open the serial port.
42 | //
43 | using namespace LibSerial ;
44 | using namespace std;
45 | SerialStream serial_port ;
46 | serial_port.Open( "/dev/ttyUSB0" ) ;
47 | if ( ! serial_port.good() )
48 | {
49 | std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
50 | << "Error: Could not open serial port."
51 | << std::endl ;
52 | exit(1) ;
53 | }
54 | //
55 | // Set the baud rate of the serial port.
56 | //
57 | serial_port.SetBaudRate( SerialStreamBuf::BAUD_57600 ) ;
58 | if ( ! serial_port.good() )
59 | {
60 | std::cerr << "Error: Could not set the baud rate." << std::endl ;
61 | exit(1) ;
62 | }
63 | //
64 | // Set the number of data bits.
65 | //
66 | serial_port.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 ) ;
67 | if ( ! serial_port.good() )
68 | {
69 | std::cerr << "Error: Could not set the character size." << std::endl ;
70 | exit(1) ;
71 | }
72 | //
73 | // Disable parity.
74 | //
75 | serial_port.SetParity( SerialStreamBuf::PARITY_NONE ) ;
76 | if ( ! serial_port.good() )
77 | {
78 | std::cerr << "Error: Could not disable the parity." << std::endl ;
79 | exit(1) ;
80 | }
81 | //
82 | // Set the number of stop bits.
83 | //
84 | serial_port.SetNumOfStopBits( 1 ) ;
85 | if ( ! serial_port.good() )
86 | {
87 | std::cerr << "Error: Could not set the number of stop bits."
88 | << std::endl ;
89 | exit(1) ;
90 | }
91 | //
92 | // Turn on hardware flow control.
93 | //
94 | serial_port.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_HARD ) ;
95 | if ( ! serial_port.good() )
96 | {
97 | std::cerr << "Error: Could not use hardware flow control."
98 | << std::endl ;
99 | exit(1) ;
100 | }
101 | //
102 | // Do not skip whitespace characters while reading from the
103 | // serial port.
104 | //
105 | serial_port.unsetf( std::ios_base::skipws ) ;
106 | //
107 | // Keep reading data from serial port and print it to the screen.
108 | //
109 |
110 | ofstream distance,temperature,humidity;
111 |
112 | char next_byte1;
113 | char next_byte2;
114 | char next_byte;
115 |
116 | int packetType;
117 | int nodeID;
118 | int sensorID;
119 | int parity;
120 | int payload;
121 |
122 | //T12N00I00P01Q13
123 | while( true )
124 | {
125 | serial_port.get(next_byte);
126 | if((char)next_byte == 'T')
127 | {
128 | serial_port.get(next_byte1);
129 | serial_port.get(next_byte2);
130 | packetType=hex_to_dec(next_byte1)*16 + hex_to_dec(next_byte2);
131 | if (packetType == 0x12)
132 | {
133 | serial_port.get(next_byte);
134 | if((char)next_byte == 'N')
135 | {
136 | serial_port.get(next_byte1);
137 | serial_port.get(next_byte2);
138 | nodeID=hex_to_dec(next_byte1)*16 + hex_to_dec(next_byte2);
139 | }
140 |
141 | serial_port.get(next_byte);
142 | if((char)next_byte == 'I')
143 | {
144 | serial_port.get(next_byte1);
145 | serial_port.get(next_byte2);
146 | sensorID=hex_to_dec(next_byte1)*16 + hex_to_dec(next_byte2);
147 | }
148 | serial_port.get(next_byte);
149 |
150 | serial_port.get(next_byte1);
151 | serial_port.get(next_byte2);
152 | payload=hex_to_dec(next_byte1)*16 + hex_to_dec(next_byte2);
153 |
154 | if((char)next_byte == 'P')
155 | {
156 | if(sensorID==TEMPERATURE)
157 | {
158 | distance.open ("arduino_distance.log");
159 | distance << payload << "\n";
160 | distance.close();
161 | }
162 |
163 | else if(sensorID==HUMIDITY)
164 | {
165 | humidity.open ("arduino_humidity.log");
166 | humidity << payload << "\n";
167 | humidity.close();
168 | }
169 |
170 | else if(sensorID==DISTANCE)
171 | {
172 | temperature.open ("arduino_temperature.log");
173 | temperature << payload << "\n";
174 | temperature.close();
175 | }
176 | }
177 | }
178 | }
179 | }
180 | std::cerr << std::endl ;
181 | return EXIT_SUCCESS ;
182 | }
183 |
184 | /// Convert HEX to Decimal
185 | #define HEX_DEC_ERROR 42
186 | int hex_to_dec(int in)
187 | {
188 | if(((in >= '0') && (in <= '9'))) return in-'0';
189 | in |= 0x20;
190 | if(((in >= 'a') && (in <= 'f'))) return in-'a' + 10;
191 | return HEX_DEC_ERROR;
192 | }
193 |
194 |
--------------------------------------------------------------------------------
/Clients/Collectd/arduino_distance.log:
--------------------------------------------------------------------------------
1 | 12
2 |
--------------------------------------------------------------------------------
/Clients/Collectd/arduino_humidity.log:
--------------------------------------------------------------------------------
1 | 27
2 |
--------------------------------------------------------------------------------
/Clients/Collectd/arduino_temperature.log:
--------------------------------------------------------------------------------
1 | 0
2 |
--------------------------------------------------------------------------------
/Clients/Collectd/arduinologger_distance.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'getoptlong'
3 |
4 | # The name of the collectd plugin, something like apache, memory, mysql, interface, ...
5 | PLUGIN_NAME = 'arduinologger-distance'
6 |
7 | def usage
8 | puts("#{$0} -h [-i ]")
9 | exit
10 | end
11 |
12 | # Main
13 | begin
14 | # Sync stdout so that it will flush to collectd properly.
15 | $stdout.sync = true
16 |
17 | # Parse command line options
18 | hostname = nil
19 | sampling_interval = 20 # sec, Default value
20 | opts = GetoptLong.new(
21 | [ '--hostid', '-h', GetoptLong::REQUIRED_ARGUMENT ],
22 | [ '--sampling-interval', '-i', GetoptLong::OPTIONAL_ARGUMENT ]
23 | )
24 | opts.each do |opt, arg|
25 | case opt
26 | when '--hostid'
27 | hostname = arg
28 | when '--sampling-interval'
29 | sampling_interval = arg.to_i
30 | end
31 | end
32 | usage if !hostname
33 |
34 | # Collection loop
35 | while true do
36 | start_run = Time.now.to_i
37 | next_run = start_run + sampling_interval
38 |
39 | # collectd data and print the values
40 | data = `cat /usr/lib/collectd/plugins/arduino_distance.log` # get 5-minute load average
41 | puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-distance #{start_run}:#{data}")
42 |
43 | # sleep to make the interval
44 | while((time_left = (next_run - Time.now.to_i)) > 0) do
45 | sleep(time_left)
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/Clients/Collectd/arduinologger_humidity.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'getoptlong'
3 |
4 | # The name of the collectd plugin, something like apache, memory, mysql, interface, ...
5 | PLUGIN_NAME = 'arduinologger-humidity'
6 |
7 | def usage
8 | puts("#{$0} -h [-i ]")
9 | exit
10 | end
11 |
12 | # Main
13 | begin
14 | # Sync stdout so that it will flush to collectd properly.
15 | $stdout.sync = true
16 |
17 | # Parse command line options
18 | hostname = nil
19 | sampling_interval = 20 # sec, Default value
20 | opts = GetoptLong.new(
21 | [ '--hostid', '-h', GetoptLong::REQUIRED_ARGUMENT ],
22 | [ '--sampling-interval', '-i', GetoptLong::OPTIONAL_ARGUMENT ]
23 | )
24 | opts.each do |opt, arg|
25 | case opt
26 | when '--hostid'
27 | hostname = arg
28 | when '--sampling-interval'
29 | sampling_interval = arg.to_i
30 | end
31 | end
32 | usage if !hostname
33 |
34 | # Collection loop
35 | while true do
36 | start_run = Time.now.to_i
37 | next_run = start_run + sampling_interval
38 |
39 | # collectd data and print the values
40 | data = `cat /usr/lib/collectd/plugins/arduino_humidity.log` # get 5-minute load average
41 | puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-humidity #{start_run}:#{data}")
42 |
43 | # sleep to make the interval
44 | while((time_left = (next_run - Time.now.to_i)) > 0) do
45 | sleep(time_left)
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/Clients/Collectd/arduinologger_temperature.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'getoptlong'
3 |
4 | # The name of the collectd plugin, something like apache, memory, mysql, interface, ...
5 | PLUGIN_NAME = 'arduinologger-temperature'
6 |
7 | def usage
8 | puts("#{$0} -h [-i ]")
9 | exit
10 | end
11 |
12 | # Main
13 | begin
14 | # Sync stdout so that it will flush to collectd properly.
15 | $stdout.sync = true
16 |
17 | # Parse command line options
18 | hostname = nil
19 | sampling_interval = 20 # sec, Default value
20 | opts = GetoptLong.new(
21 | [ '--hostid', '-h', GetoptLong::REQUIRED_ARGUMENT ],
22 | [ '--sampling-interval', '-i', GetoptLong::OPTIONAL_ARGUMENT ]
23 | )
24 | opts.each do |opt, arg|
25 | case opt
26 | when '--hostid'
27 | hostname = arg
28 | when '--sampling-interval'
29 | sampling_interval = arg.to_i
30 | end
31 | end
32 | usage if !hostname
33 |
34 | # Collection loop
35 | while true do
36 | start_run = Time.now.to_i
37 | next_run = start_run + sampling_interval
38 |
39 | # collectd data and print the values
40 | data = `cat /usr/lib/collectd/plugins/arduino_temperature.log` # get 5-minute load average
41 | puts("PUTVAL #{hostname}/#{PLUGIN_NAME}/gauge-temperature #{start_run}:#{data}")
42 |
43 | # sleep to make the interval
44 | while((time_left = (next_run - Time.now.to_i)) > 0) do
45 | sleep(time_left)
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/Clients/Collectd/collectd.conf:
--------------------------------------------------------------------------------
1 | ## ADD these lines at the end of your existing : "/etc/collect/collect.conf" (only tested on Ubuntu 12.10)
2 |
3 | ## This is not totally correct (syslog shows warnings)
4 | LoadPlugin exec
5 |
6 | # userid plugin executable plugin args
7 | Exec "jeroen" "/usr/lib/collectd/plugins/arduinologger_distance.rb" "-h" "ArduinoLogger" "-i" "1"
8 |
9 |
10 | LoadPlugin exec
11 |
12 | # userid plugin executable plugin args
13 | Exec "jeroen" "/usr/lib/collectd/plugins/arduinologger_temperature.rb" "-h" "ArduinoLogger" "-i" "1"
14 |
15 |
16 | LoadPlugin exec
17 |
18 | # userid plugin executable plugin args
19 | Exec "jeroen" "/usr/lib/collectd/plugins/arduinologger_humidity.rb" "-h" "ArduinoLogger" "-i" "1"
20 |
--------------------------------------------------------------------------------
/Clients/Collectd/collectd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeroendoggen/Arduino-serial-messaging/87bdc590bfb85e6d31165f1c8e87f0d09042c8cc/Clients/Collectd/collectd.png
--------------------------------------------------------------------------------
/Clients/Processing/PacketInspector_v1.pde:
--------------------------------------------------------------------------------
1 | String typedText = "";
2 |
3 | PFont font;
4 | import processing.serial.*;
5 |
6 | Serial myPort; // Create object from Serial class
7 |
8 | int portNumber = 0;
9 | byte[] inBuffer = new byte[17];
10 |
11 | byte msgType;
12 | byte nodeID;
13 | byte sensorID;
14 | byte payload;
15 | byte parity;
16 | byte command;
17 |
18 | int lf=10;
19 |
20 | void setup() {
21 | size(440, 80);
22 | font = createFont("Arial-Black-48.vlw", 10);
23 |
24 | String portName = Serial.list()[portNumber];
25 | myPort = new Serial(this, portName, 115200);
26 | myPort.bufferUntil(lf);
27 | myPort.clear();
28 |
29 | background(245);
30 | }
31 |
32 |
33 | void draw() {
34 | drawduobutton(10,10,220,0,"","Hex","Decimal");
35 | drawduobutton(80,10,220,0,"MsgType",msgType,int(msgType));
36 | drawduobutton(150,10,220,0,"NodeID",nodeID,int(nodeID));
37 | drawduobutton(220,10,220,0,"SensorID",sensorID,int(sensorID));
38 | drawduobutton(290,10,220,0,"Payload",payload,int(payload));
39 | drawduobutton(360,10,220,0,"Parity",parity,int(parity));
40 | }
41 |
42 | void drawduobutton(int right, int down, int bgcolor, int textcolor, String buttontext, byte dataByte,int buttondata){
43 | drawbutton(right, down, bgcolor, textcolor, buttontext,70);
44 | drawbutton(right, down+20, bgcolor+30, textcolor, dataByte,70);
45 | drawbutton(right, down+40, bgcolor+30, textcolor, buttondata,70);
46 | }
47 |
48 | void drawduobutton(int right, int down, int bgcolor, int textcolor, String buttontext1, String buttontext2, String buttontext3){
49 | drawbutton(right, down, bgcolor, textcolor, buttontext1,70);
50 | drawbutton(right, down+20, bgcolor+30, textcolor, buttontext2,70);
51 | drawbutton(right, down+40, bgcolor+30, textcolor, buttontext3,70);
52 | }
53 |
54 | void drawbutton(int right, int down, int bgcolor, int textcolor, String buttontext, int width){
55 | int height=20;
56 | if(bgcolor==1) fill(255,0,0);
57 | else if(bgcolor==2)fill(0,255,0);
58 | else if(bgcolor==3)fill(0,0,255);
59 | else fill(bgcolor);
60 |
61 | rect(right, down, width, height);
62 | textAlign(CENTER);
63 | fill(textcolor);
64 | text(buttontext, right+(width/2), down+(height/1.2));
65 | }
66 |
67 | void drawbutton(int right, int down, int bgcolor, int textcolor, int buttondata, int width){
68 | int height=20;
69 | if(bgcolor==1) fill(255,0,0);
70 | else if(bgcolor==2)fill(0,255,0);
71 | else if(bgcolor==3)fill(0,0,255);
72 | else fill(bgcolor);
73 |
74 | rect(right, down, width, height);
75 | textAlign(CENTER);
76 | fill(textcolor);
77 | text(int(buttondata), right+(width/2), down+(height/1.2));
78 | }
79 |
80 | void drawbutton(int right, int down, int bgcolor, int textcolor, byte buttondata, int width){
81 | int height=20;
82 | if(bgcolor==1) fill(255,0,0);
83 | else if(bgcolor==2)fill(0,255,0);
84 | else if(bgcolor==3)fill(0,0,255);
85 | else fill(bgcolor);
86 |
87 | rect(right, down, width, height);
88 | textAlign(CENTER);
89 | fill(textcolor);
90 | text(hex(buttondata), right+(width/2), down+(height/1.2));
91 | }
92 |
93 | void serialEvent(Serial thisPort) {
94 |
95 | while (thisPort.available() > 0) {
96 | int byteCount = thisPort.readBytesUntil(lf, inBuffer);
97 | }
98 |
99 | msgType=byte(Character.getNumericValue(inBuffer[1])*16 + Character.getNumericValue(inBuffer[2]));
100 | nodeID=byte(Character.getNumericValue(inBuffer[4])*16 + Character.getNumericValue(inBuffer[5]));
101 | sensorID=byte(Character.getNumericValue(inBuffer[7])*16 + Character.getNumericValue(inBuffer[8]));
102 | payload=byte(Character.getNumericValue(inBuffer[10])*16 + Character.getNumericValue(inBuffer[11]));
103 | parity=byte(Character.getNumericValue(inBuffer[13])*16 + Character.getNumericValue(inBuffer[14]));
104 | }
105 |
--------------------------------------------------------------------------------
/Clients/Processing/README.md:
--------------------------------------------------------------------------------
1 | ## Arduino sensor logging with collectd & RRDtool
2 |
3 | Small application written in the processing programming language (~Java) that shows the contents of the last incoming packet in a GUI.
4 |
5 | Screenshot:
6 |
7 | 
8 |
9 | ## Links
10 |
11 | * [http://processing.org](http://processing.org)
--------------------------------------------------------------------------------
/Clients/Processing/ScreenShot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeroendoggen/Arduino-serial-messaging/87bdc590bfb85e6d31165f1c8e87f0d09042c8cc/Clients/Processing/ScreenShot.png
--------------------------------------------------------------------------------
/Clients/Python/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 |
8 | # Distribution / packaging
9 | bin/
10 | build/
11 | develop-eggs/
12 | dist/
13 | eggs/
14 | lib/
15 | lib64/
16 | parts/
17 | sdist/
18 | var/
19 | *.egg-info/
20 | .installed.cfg
21 | *.egg
22 |
23 | # Installer logs
24 | pip-log.txt
25 |
26 | # Unit test / coverage reports
27 | .tox/
28 | .coverage
29 | nosetests.xml
30 | coverage.xml
31 |
32 | # Translations
33 | *.mo
34 |
35 | # Mr Developer
36 | .mr.developer.cfg
37 | .project
38 | .pydevproject
39 |
--------------------------------------------------------------------------------
/Clients/Python/README.md:
--------------------------------------------------------------------------------
1 | SerialPacket Controller: Controller for the SerialPacket protocol
2 | =================================================================
3 | A controller application to show Python to Arduino communication using the SerialPacket protocol
4 |
5 | Program flow:
6 | 1. Connect to the Arduino over the serial port
7 | 2. Start the "SerialPacket Controller"
8 | 3. The controller reads incoming data
9 | 4. The controller starts polling for commands
10 |
11 | Installation:
12 | -------------
13 | * Install the Debian package: ``sudo dpkg -i python-sp-controller_0.x.x-x_all.deb``
14 | * Download the source and run ``sudo python setup.py install``
15 |
16 | Usage:
17 | ------
18 | * Start the program with: ``python -m sp_controller``
19 |
20 |
21 | Requirements:
22 | -------------
23 | * Python 2.6+
24 | * python-serial (e.g. Ubuntu package)
25 |
26 |
27 | Limitations:
28 | ------------
29 | * probably still some bugs
30 |
31 | License:
32 | --------
33 | If not stated otherwise sp_controller is distributed in terms of the GPLv2 software license.
34 | See COPYING in the distribution for details.
35 |
36 | Bug reports:
37 | ------------
38 | * Jeroen Doggen
39 |
40 | Roadmap:
41 | --------
42 |
43 | 0.3: ??
44 |
45 | Changelog:
46 | ----------
47 |
48 | 0.0.2: First threaded version
49 | * Threads started from controller
50 | * Thread 1: Read data from serial port (SerialCommunication class)
51 | * Thread 2: Poll the database for commands (DatabaseCommunication class)
52 | * Sleeptime for all thread can be changed at runtime
53 |
54 | 0.0.1: Initial version:
55 | * startup using cli arguments
56 | * working PyPI compatible python package
57 | * connect to serial
58 | * print info on cli + write to logfile
59 |
--------------------------------------------------------------------------------
/Clients/Python/makeDebian.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Small script to create the Debian package & install it when it is done
4 |
5 | echo "Starting package build process"
6 |
7 | python setup.py --command-packages=stdeb.command sdist_dsc
8 |
9 | cd deb_dist/sp-controller-0.0.1/
10 |
11 | dpkg-buildpackage -rfakeroot -uc -us
12 |
13 | cd ..
14 |
15 | sudo dpkg -i python-sp-controller_0.0.1-1_all.deb
16 |
17 |
--------------------------------------------------------------------------------
/Clients/Python/setup.py:
--------------------------------------------------------------------------------
1 | """Setup file for sp
2 |
3 | Define the options for the "sp_controller" package
4 | Create source Python packages (python setup.py sdist)
5 | Create binary Python packages (python setup.py bdist)
6 |
7 | """
8 | from distutils.core import setup
9 |
10 | from sp_controller import __version__
11 |
12 |
13 | with open('README.md') as readme_file:
14 | LONG_DESCRIPTION = readme_file.read()
15 |
16 | setup(name='sp_Controller',
17 | version=__version__,
18 | description='Controller for the SerialPacket protocol',
19 | long_description=LONG_DESCRIPTION,
20 | author='Jeroen Doggen',
21 | author_email='jeroendoggen@gmail.com',
22 | url='none',
23 | packages=['sp_controller'],
24 | package_data={'sp_controller': ['*.py', '*.conf']},
25 | license='LGPL-v2',
26 | platforms=['Linux'],
27 | )
28 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/__init__.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: Initialize the package
2 |
3 | This file is needed to import the module properly
4 | The version number is used to generate the PyPI package
5 |
6 | """
7 | __version__ = "0.0.2"
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/__main__.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: Main file to run
2 |
3 | This file is needed to be able to run a Python program in a folder directly
4 | by calling "Python foldername"
5 |
6 | """
7 |
8 | from sp_controller.main import run
9 |
10 | if __name__ == '__main__':
11 | run()
12 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/controller.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: core code
2 |
3 | TODO write some comments
4 | TODO try to restart the threads when they exit
5 | - when disconnecting the usb the serial thread stops
6 | - when reconnecting, the thread should try to restart (after a timeout)
7 |
8 | """
9 | from __future__ import print_function, division # We require Python 2.6+
10 | import time
11 | import sys
12 | from Queue import Queue
13 |
14 |
15 | from sp_controller.settings import Settings
16 |
17 |
18 | class QueueSetting:
19 | """The different queues for input/output"""
20 | def __init__(self, sensordata_queue, cmd_reply_queue, cmd_queue):
21 | self.sensordata_queue = sensordata_queue
22 | self.cmd_reply_queue = cmd_reply_queue
23 | self.cmd_queue = cmd_queue
24 |
25 |
26 | class Controller:
27 | """Controller class: does the core of the work"""
28 | sensordata_queue = Queue()
29 | cmd_reply_queue = Queue()
30 | cmd_queue = Queue()
31 | payload_counter = 0
32 |
33 | def __init__(self):
34 | """ Initialize the controller """
35 | self.queue_settings = QueueSetting(self.sensordata_queue,
36 | self.cmd_reply_queue,
37 | self.cmd_queue)
38 |
39 | self.config = Settings(self.queue_settings)
40 | self.serial_read_thread = self.config.get_serial_read()
41 | self.serial_write_thread = self.config.get_serial_write()
42 | self.errors = 0
43 |
44 | def run(self):
45 | """The main thread for the controller"""
46 | self.start_serial_communication_threads()
47 | while True:
48 | try:
49 | time.sleep(2)
50 | self.send_command()
51 | except KeyboardInterrupt:
52 | print("Program stopped by keyboard interrupt")
53 | sys.exit(1)
54 |
55 | def send_command(self):
56 | # Just send some dummy packets (with a counter for the payload)
57 | self.cmd_queue.put((1, self.payload_counter, 2))
58 | print("A command has been placed in the queue")
59 |
60 | self.payload_counter += 1
61 | if (self.payload_counter is 255):
62 | self.payload_counter = 0
63 |
64 | def start_serial_communication_threads(self):
65 | """Start serial communication thread"""
66 | self.serial_write_thread.daemon = True
67 | self.serial_write_thread.start()
68 | self.serial_read_thread.daemon = True
69 | self.serial_read_thread.start()
70 |
71 | def exit_value(self):
72 | """TODO: Generate the exit value for the application."""
73 | if (self.errors == 0):
74 | return 0
75 | else:
76 | return 42
77 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/infoprinter.py:
--------------------------------------------------------------------------------
1 | """ Print information messages
2 |
3 | This is currently used to keep the info messages out of the other code
4 |
5 | """
6 |
7 | from __future__ import print_function, division # We require Python 2.6+
8 |
9 |
10 | def double_line():
11 | """Print a double line"""
12 | print ("=============================================================")
13 |
14 |
15 | def single_line():
16 | """Print a single line"""
17 | print ("-------------------------------------------------------------")
18 |
19 |
20 | def top():
21 | """Print the top of the cli message"""
22 | print ("")
23 | double_line()
24 | print ("Starting sp_controller...")
25 |
26 |
27 | def programflow(serial_port):
28 | """Print the program flow"""
29 | print ("")
30 | print ("Program flow: ")
31 | print (" 1. Connect to the Arduino on port: " + serial_port)
32 | print (" 2. Start polling for commands")
33 | print (" 3. Start writing incoming data to the terminal")
34 | print (" repeat forever... ")
35 | print ("")
36 |
37 |
38 | def startup_info(serial_port):
39 | """Print an overview of the startup info"""
40 | top()
41 | programflow(serial_port)
42 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/main.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: core code
2 |
3 | This file is needed to import the module properly
4 | Copyright (C) 2013 Jeroen Doggen
5 |
6 | """
7 |
8 | import sys
9 |
10 | from sp_controller.controller import Controller
11 |
12 |
13 | def run():
14 | """Run the main program"""
15 | controller = Controller()
16 | controller.run()
17 | return(controller.exit_value())
18 |
19 |
20 | if __name__ == "__main__":
21 | sys.exit(run())
22 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/serialcommunication.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: serial communication
2 |
3 | Serial communication class
4 | - Connect to the serial port
5 | - Allow a thread to be started to read data from the serial port
6 |
7 | """
8 |
9 | from __future__ import print_function # We require Python 2.6+
10 |
11 | import sys
12 | import threading
13 | import time
14 |
15 | try:
16 | import serial
17 | except ImportError as exc:
18 | print("Error: failed to import pyserial module")
19 | print("Solution: you probably need to install the pyserial module")
20 | sys.exit(0)
21 |
22 | from sp_controller.serialparser import SerialParser
23 |
24 |
25 | class SerialCommunication(threading.Thread):
26 | """SerialCommunication: handling all serial communication in a thread"""
27 | def __init__(self,
28 | identification,
29 | serialport_settings,
30 | logger,
31 | sleeptime,
32 | queue_settings):
33 | """Initialize the serial port object."""
34 | self.logger = logger
35 | self.sleeptime = sleeptime
36 | self.sensordata_queue = queue_settings.sensordata_queue
37 | self.cmd_reply_queue = queue_settings.cmd_reply_queue
38 | self.cmd_queue = queue_settings.cmd_queue
39 | self.identification = identification
40 | self.serial_connect(serialport_settings.serial_port,
41 | serialport_settings.baudrate)
42 | self.parser = SerialParser()
43 | threading.Thread.__init__(self)
44 |
45 | def run(self):
46 | """This function will be called when the thread starts"""
47 | while True:
48 | time.sleep(self.sleeptime)
49 | # print(self.identification)
50 | if self.identification == "Packet_receiver":
51 | self.get_packet()
52 | if self.identification == "Command_transmitter":
53 | self.send_commands()
54 |
55 | def check_baudrate(self, baudrate):
56 | """TODO: implement this (now the program hangs on invalid baudrates)"""
57 | pass
58 | # if baudrate != 115200:
59 | # print("Baudrate error")
60 | # sys.exit()
61 |
62 | def serial_connect(self, serial_port, baudrate):
63 | """Connect to serial port"""
64 | try:
65 | self.check_baudrate(baudrate)
66 | self.ser = serial.Serial(serial_port, baudrate)
67 | self.ser.flush()
68 | self.logger.info(self.identification
69 | + " : Connected to serial port: "
70 | + serial_port
71 | + " with speed:" + str(baudrate))
72 | print(self.identification
73 | + " : connected to serial port: ", end="")
74 | print(serial_port, end="")
75 | print(" with speed: ", end="")
76 | print(baudrate)
77 | except:
78 | self.logger.critical("Unable to connect to serial port: "
79 | + serial_port
80 | + " with speed:"
81 | + str(baudrate))
82 | print("Unable to connect to serial port: ", end="")
83 | print(serial_port, end="")
84 | print(" with speed: ", end="")
85 | print(baudrate)
86 | sys.exit(1)
87 |
88 | def read_line(self):
89 | """Read one line of text over the serial port"""
90 | try:
91 | line = self.ser.readline()[:-1]
92 | # line = self.ser.readline().decode('utf-8')[:-1]
93 | return(line)
94 | except IOError:
95 | self.logger.critical("Lost serial connection")
96 | print ("Lost serial connection")
97 | #self.failed_test_list.append(current_test)
98 | sys.exit(1)
99 |
100 | def set_sleeptime(self, sleeptime):
101 | """Set the sleeptime for the thread"""
102 | self.sleeptime = sleeptime
103 |
104 | def get_packet(self):
105 | """Get one serial packet (one line of data)"""
106 | packet = self.read_line()[:-1]
107 | print("Incoming packet: " + packet) # Print packet (HEX format)
108 | packet = self.parser.parse(packet)
109 | print(packet) # Print out all info about the packet (human readable)
110 | print("") # Print empty line
111 | if packet != 0:
112 | self.sensordata_queue.put(packet)
113 |
114 | def send_commands(self):
115 | """Send commands from the queue to the serial ports"""
116 | if not self.cmd_queue.empty():
117 | command = self.cmd_queue.get()
118 | #print(command)
119 | #self.cmd_queue.join
120 | command_id = command[0]
121 | payload = command[1]
122 | node_id = command[2]
123 | self.send_command(command_id, payload, node_id)
124 |
125 | # print(command)
126 |
127 | def send_old_command(self, value):
128 | """Send a command packet: compatible with command queue (deprecated: june 2013)"""
129 | # print(value)
130 | value = map(int, value) # convert command elements in list to int
131 | # print(value)
132 | value = value[0] # get first int from list
133 | print("Command in db: ", value)
134 | if (value < 256):
135 | #value = self.converter.db_to_serial(value)
136 | value = hex(value) # convert to hex string
137 | # print(value)
138 | value = value[2:4] # trow away 0x in front of hex string
139 | # print(value)
140 | parity = 0x01 ^ 0x00 ^ 0x12 ^ int(value, 16) # calculate parity
141 | parity = hex(parity) # convert to hex string
142 | parity = parity[2:4] # throw away 0x in front of sting
143 | ## parity = "EC"
144 | self.ser.write("T01N00I12P" + str(value) + "Q"
145 | + str(parity) + "\r")
146 | print("Command for Arduino: " + str(value), "HEX")
147 |
148 | def send_command(self, command_id, payload, node_id):
149 | """Send a command packet"""
150 | # Debug info:
151 | print("Command: ", self.hex_converter(command_id))
152 | print("Payload: ", self.hex_converter(payload))
153 | print("Node_id: ", self.hex_converter(node_id))
154 |
155 | # Calculate parity field:
156 | parity = 0x01 ^ node_id ^ command_id ^ payload
157 | parity = self.hex_converter(parity)
158 |
159 | # Convert to hex
160 | command_id = self.hex_converter(command_id)
161 | payload = self.hex_converter(payload)
162 | node_id = self.hex_converter(node_id)
163 |
164 | # Create packet
165 | packet = "T01" + "N" + str(node_id) + "I" + str(command_id) + "P" + str(payload) + "Q" + str(parity) + "\r"
166 | print(packet)
167 |
168 | # Send packet
169 | self.ser.write(packet)
170 | print("")
171 |
172 | def hex_converter(self, value):
173 | # print("Input: ", end="")
174 | # print(value)
175 | value = hex(value)
176 | value = value[2:4]
177 | if (int(value,16) < 16):
178 | value = "0" + value
179 | # print("Output: ", end="")
180 | # print(value)
181 | return(value)
182 |
183 |
184 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/serialparser.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: serial parser
2 |
3 | Serial parser class
4 |
5 | """
6 |
7 | from __future__ import print_function # We require Python 2.6+
8 | import datetime
9 |
10 |
11 | class SerialParser():
12 | """SerialParser: parser for SerialPacket data"""
13 | def __init__(self):
14 | pass
15 | #self.converter = DataConverter()
16 |
17 | def parse(self, packet):
18 | """Parse a packet"""
19 | self.now = datetime.datetime.now()
20 | if self.validate_packet(packet):
21 | if self.get_packet_type(packet) == 0x01: #
22 | return(self.parse_data(packet))
23 | if self.get_packet_type(packet) == 0x02: # COMMAND_REPLY
24 | return(self.parse_data(packet))
25 | else:
26 | return 0
27 |
28 | def parse_data(self, packet):
29 | """Parse the data"""
30 | # print (self.get_sensor_id(packet),
31 | # " becomes ",
32 | # self.converter.serial_to_db(self.get_sensor_id(packet)))
33 | return(self.get_node_id(packet),
34 | self.get_sensor_id(packet),
35 | self.get_payload(packet),
36 | str(self.now))
37 |
38 | def validate_packet(self, packet):
39 | """Validate an incoming packet using parity control"""
40 | if len(packet) == 15:
41 | self.received_parity = self.get_quality_check(packet)
42 | self.calculated_parity = (int(packet[1:3], 16)
43 | ^ int(packet[4:6], 16)
44 | ^ int(packet[7:9], 16)
45 | ^ int(packet[10:12], 16))
46 | # print(self.received_parity)
47 | # print(self.calculated_parity)
48 | if self.received_parity == self.calculated_parity:
49 | return True
50 | else:
51 | return False
52 |
53 | def get_packet_type(self, packet):
54 | """Get the packet type"""
55 | if self.validate_packet(packet):
56 | if packet[0] == 'T':
57 | return self.hex_to_dec(packet[1:3])
58 | else:
59 | return 0
60 |
61 | def get_node_id(self, packet):
62 | """Get the node id"""
63 | if packet[3] == 'N':
64 | return self.hex_to_dec(packet[4:6])
65 | else:
66 | return 0
67 |
68 | def get_sensor_id(self, packet):
69 | """Get the sensor id"""
70 | if packet[6] == 'I':
71 | return self.hex_to_dec(packet[7:9])
72 | else:
73 | return 0
74 |
75 | def get_payload(self, packet):
76 | """Get the payload"""
77 | if packet[9] == 'P':
78 | return self.hex_to_dec(packet[10:12])
79 | else:
80 | return 0
81 |
82 | def get_quality_check(self, packet):
83 | """Get the parity 'quality check'"""
84 | if packet[12] == 'Q':
85 | return self.hex_to_dec(packet[13:15])
86 | else:
87 | return 0
88 |
89 | def hex_to_dec(self, hexvalue):
90 | """Convert hex value to decimal"""
91 | return int(hexvalue, 16)
92 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/settings.py:
--------------------------------------------------------------------------------
1 | """ sp_controller: Settings class
2 |
3 | get the cli arguments
4 | set the logfile
5 | set the serial port
6 |
7 | """
8 |
9 | from __future__ import print_function, division # We require Python 2.6+
10 |
11 | import argparse
12 | import logging
13 | import os
14 | import sys
15 |
16 | import infoprinter
17 | from sp_controller.serialcommunication import SerialCommunication
18 | from sp_controller.__init__ import __version__
19 |
20 |
21 | DEFAULT_PORT = "/dev/ttyUSB0"
22 | DEFAULT_BAUDRATE = 115200
23 | DEFAULT_LOGFILE = "sp_controller.log"
24 | DEFAULT_SERIAL_READ_SLEEPTIME = 0.1
25 | DEFAULT_SERIAL_WRITE_SLEEPTIME = 0.1
26 | #keep this around 0.5 (Arduino gets confused!! (buffer overflow?)
27 | DEFAULT_PATH = os.getcwd() + "/"
28 |
29 |
30 | class SerialportSetting:
31 | """The serial port settings"""
32 | def __init__(self, serial_port, baudrate):
33 | self.serial_port = serial_port
34 | self.baudrate = baudrate
35 |
36 |
37 | class Settings:
38 | """Configure the settings of the program"""
39 | path = DEFAULT_PATH
40 | logfile = path + DEFAULT_LOGFILE
41 |
42 | serial_read_sleeptime = DEFAULT_SERIAL_READ_SLEEPTIME
43 | serial_write_sleeptime = DEFAULT_SERIAL_WRITE_SLEEPTIME
44 |
45 | parser = argparse.ArgumentParser(
46 | prog="sp_controller",
47 | formatter_class=argparse.RawDescriptionHelpFormatter,
48 | description="sp_controller commandline arguments:",
49 | epilog="Report bugs to jeroendoggen@gmail.com.")
50 |
51 | def __init__(self, queue_settings):
52 | """Initialize"""
53 | self.serialport_settings = SerialportSetting(DEFAULT_PORT,
54 | DEFAULT_BAUDRATE)
55 | self.queue_settings = queue_settings
56 | self.cli_arguments()
57 | infoprinter.startup_info(self.serialport_settings.serial_port)
58 | self.set_logfile()
59 | self.set_serialport()
60 |
61 | def cli_arguments(self):
62 | """Configure a read all the cli arguments."""
63 | self.configure_cli_arguments()
64 | self.get_cli_arguments()
65 |
66 | def configure_cli_arguments(self):
67 | """Configure all the cli arguments."""
68 | self.parser.add_argument("-p", metavar="port",
69 | help="Set the name of the serial port")
70 | self.parser.add_argument("-f", metavar="file",
71 | help="Set the name of the logfile")
72 | self.parser.add_argument("-b", metavar="baudrate",
73 | help="Set the baudrate of the serial port")
74 |
75 | def get_cli_arguments(self):
76 | """Read all the cli arguments."""
77 | args = self.parser.parse_args()
78 | if (args.p is not None):
79 | self.serialport_settings.serial_port = args.p
80 | if (args.b is not None):
81 | self.serialport_settings.baudrate = args.b
82 | if (args.f is not None):
83 | self.logfile = self.path + args.f
84 |
85 | def set_logfile(self):
86 | """Set the logfile where we will write error & info messages"""
87 | try:
88 | logging.basicConfig(filename=self.logfile,
89 | level=logging.DEBUG,
90 | format="%(asctime)s %(name)s %(levelname)s %(message)s")
91 | self.logger = logging.getLogger(__name__)
92 | except IOError:
93 | print("Unable to open logfile")
94 | print("Do you have write access in the current folder?")
95 | sys.exit(0)
96 |
97 | def set_serialport(self):
98 | """Set the serial port"""
99 | #TODO: they should only get one queue (not two)
100 | self.sp_read = SerialCommunication("Packet_receiver ",
101 | self.serialport_settings,
102 | self.logger,
103 | self.serial_read_sleeptime,
104 | self.queue_settings)
105 | self.sp_write = SerialCommunication("Command_transmitter",
106 | self.serialport_settings,
107 | self.logger,
108 | self.serial_write_sleeptime,
109 | self.queue_settings)
110 |
111 | def get_serial_read(self):
112 | """Get the serialcommunication object (used in controller)"""
113 | return(self.sp_read)
114 |
115 | def get_serial_write(self):
116 | """Get the serialcommunication object (used in controller)"""
117 | return(self.sp_write)
118 |
--------------------------------------------------------------------------------
/Clients/Python/sp_controller/tests/test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 |
4 | class TestTheSuite(unittest.TestCase):
5 | """A placeholder for unit tests of this Python program"""
6 |
7 | def setUp(self):
8 | self.seq = range(10)
9 |
10 | def test_exitValueZero(self):
11 | self.assertEqual(0, 0)
12 |
13 | if __name__ == '__main__':
14 | unittest.main()
15 |
--------------------------------------------------------------------------------
/Documentation/latex/refman.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeroendoggen/Arduino-serial-messaging/87bdc590bfb85e6d31165f1c8e87f0d09042c8cc/Documentation/latex/refman.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Library to exchange short messages (sensordata, commands) between an Arduino and a software application running on a PC. (Linux, embedded Linux, Windows, OS X) (clients currently under development)
2 |
3 | Both sides are able send and receive a range of "standardised" messages over the serial port. All communication is done by sending short human readable ASCII messages. We define several standard command and data packet IDs to provide interoperability between different applications.
4 |
5 | The protocol was designed to be relatively easy to comprehend and process by both human and computer.
6 | * A standardised message structure (more info below)
7 | * All fields in a message are separated by delimiters (just a letter indicating what the next field will be)
8 | * All communication is in HEX ASCII values (to allow human and computer to understand the packets)
9 | * Invalid messages are detected by calculating the parity (XOR all serial bytes)
10 |
11 | ## The Message Types
12 |
13 | The library support seven basic packet types.
14 |
15 | * "Command": start motor, blink LED, go to sleep mode,...
16 | * "Command Reply": e.g. motor started, LED blinking, going to sleep mode now,...
17 | * "8-bit Data": (standard Arduino Byte type): e.g. temperature is 25 C, distance is 50 cm, humidity is 56%
18 | * "16-bit Data": (standard Arduino int type): e.g. temperature is -25 C, distance is 310 cm, time is 16200 seconds, ...
19 | * "Data array": send multiple sensor measurements in one burst (useful when sampling very rapidly)
20 | * "Data request": e.g. send me the temperature, distance, humidity, ...
21 | * "Data array request": e.g. send me a burst of measurements
22 |
23 | More info in [`defines.h`](https://github.com/jeroendoggen/Arduino-serial-messaging/blob/master/SerialPacket/defines.h)
24 |
25 | ## Standard Messages
26 |
27 | *Data messages* are used when we want to send sensor data from the Arduino to applications running on a PC. [More info](https://github.com/jeroendoggen/Arduino-serial-messaging/wiki/Sensordata-messages)
28 |
29 | *Command messages* are used when we want to send instructions from one application to the Arduino module. [More info](https://github.com/jeroendoggen/Arduino-serial-messaging/wiki/Command-messages)
30 |
31 | We define several standard command and data message IDs. The actual meaning of the payload of these messages is standardised to provide interoperability between different applications (00h -> 7Fh). Half of the packet IDs are undefined (80h -> FFh). These IDs can be chosen based on the needs of your own application.
32 |
33 |
34 | ## Example Messages
35 |
36 | Command message **T01N00I12PFFQ21** : "set motor speed of 'Arduino zero' to +100%:
37 |
38 | * **T01**: Type 01: Command message
39 | * **N00**: Number 00: Node number 00 (is the destination)
40 | * **I12**: CommandID 12: Set motor speed
41 | * **PFF**: Payload FF: full speed (range: 0 (reverse) -> 80 (stopped) -> FF (forward))
42 | * **Q21**: Quality 21: parity byte is 21
43 |
44 | Data message **T12N00I10P08Q0A** : "temperature of 'Arduino zero' is 8 degrees"
45 |
46 | * **T12**: Type 12: Data message (1 byte payload)
47 | * **N00**: Number 00: Node number 00 (is the source)
48 | * **I10**: SensorID 10: Temperature
49 | * **P08**: Payload 08: 8 degrees
50 | * **Q0A**: Quality 0A: parity byte is 0A
51 |
52 |
53 | ## Sending Messages from Arduino Code
54 |
55 | * sendCommand(commandID,payload)
56 | * sendCommandReply(commandID,payload)
57 |
58 | * sendData(sensorID,payload)
59 | * sendDataRequest(sensorID,payload)
60 |
61 | * sendDataArray(sensorID,payload)
62 | * sendDataArrayRequest(sensorID,payload)
63 |
64 | Example sketch: [`SendPackets.ino`](https://github.com/jeroendoggen/Arduino-serial-messaging/blob/master/SerialPacket/examples/SendPackets/SendPackets.ino)
65 |
66 | ## PC Clients
67 |
68 | * [Python library](https://github.com/jeroendoggen/Arduino-serial-messaging/tree/master/Clients/Python): receive & send packets (using queues & threads)
69 | * [C# library](https://github.com/jeroendoggen/Arduino-serial-messaging/tree/master/Clients): send & receive messages (coming soon)
70 | * [RRDTool sensorlogging](https://github.com/jeroendoggen/Arduino-serial-messaging/tree/master/Clients/Collectd): write Arduino sensor data into an RRDtool database using collectd
71 | * [Packet Inspector](https://github.com/jeroendoggen/Arduino-serial-messaging/tree/master/Clients/Processing): a GUI written in the Processing language to show a incoming data packets
72 |
--------------------------------------------------------------------------------
/SerialPacket/Protocol.txt:
--------------------------------------------------------------------------------
1 | Old info below!!
2 |
3 | Packet types:
4 | 1. Command + {get,set}
5 | Format: "Type:01 NodeID:02 CommandID:06 Data:00 Parity:03"
6 |
7 | 2. Command + {ack,reply}
8 | Format: "Type:02 NodeID:02 CommandID:06 Data:05 Parity:05"
9 |
10 | 3. Data request + {payload}
11 | (requests correspond to type4 packets)
12 | Format: "Type:03 NodeID:02 SensorID:04 Data:00 Parity:05"
13 |
14 | 4. Data + {payload}
15 | Format: "Type:04 NodeID:02 SensorID:04 Data:05 Parity:07"
16 |
17 | 5. Aggregated data + {array payload}
18 | Format: "Type:05 NodeID:02 SensorID:04 Data:0102030405 Parity:02"
19 |
20 | Older info below!!
21 |
22 | Sensor Pakket:
23 | --------------
24 |
25 | Voorbeeld:
26 | TY0NI1SI1VA25PAxx : Sensor pakket, van node 1, afstandsensor, 25 cm
27 | TY0NI1SI8VA32PAxx : Sensor pakket, van node 1, temperatuurssensor, 32 graden
28 | TY0NI1SI32VA25.32.70PAxx : Sensor pakket, van node 1, 25 cm, 32 graden, 70% vocht
29 |
30 | SI: Sensor ID
31 | 0: state
32 | 1: afstand
33 | 8: temperatuur
34 | 16: vochtigheid
35 | 32: composite sensordata: afstand.temperatuur.vochtigheid
36 |
37 | VA: Value: de sensordata: tussen 0 en 255
38 |
39 | States:
40 | 0: Initialising system
41 | 1: Started
42 | 2: Stopped
43 | 3: Motor running
44 | 4: Motor stopped
45 | 5: Error
46 | 6: Lost uplink
47 |
48 | PA: Parity
49 |
50 | Commando Pakket:
51 | ----------------
52 |
53 | Voorbeeld:
54 | TY1NI0CM0 : Commando pakket, voor node 0, stop motor
55 | TY1NI1CM2VA50 : Commando pakket, voor node 1, set motorspeed 50%
56 |
57 | CM:
58 | 0: Stop motor
59 | 1: Start motor
60 | 2: Set motorspeed + payload (0 - 100 %)
61 | 3: Set sensor samplerate + payload (100 ms - 10 s)
62 | 4: Set upload rate + payload (1 s -> 100 s) ?
63 | 5:
64 |
--------------------------------------------------------------------------------
/SerialPacket/SerialPacket.cpp:
--------------------------------------------------------------------------------
1 | // SerialPacket.cpp - Library for sending serial data packets
2 | // Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
3 | // For more information: variable declaration, changelog,... see SerialPacket.h
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 |
19 | ///
20 | /// SerialPacket.cpp - Library for sending sensor data packets over UART.
21 | /// For more information: variable declaration, changelog,... see SerialPacket.h
22 | ///
23 |
24 | #include
25 | #include "SerialPacket.h"
26 | #include "defines.h"
27 |
28 | ///
29 | /// Constructor
30 | ///
31 | SerialPacket::SerialPacket() : _inputChar()
32 | {
33 | _inComingPacketComplete = false;
34 | _incomingCounter=0;
35 | incomingPacket.packetType=0;
36 | incomingPacket.nodeID=0;
37 | incomingPacket.sensorID=0;
38 | incomingPacket.commandID=0;
39 | incomingPacket.payload=0;
40 | incomingPacket.parity=0;
41 | newPacket = false;
42 | }
43 |
44 | ///
45 | /// Begin using default settings:
46 | /// - speed: 115200 baud
47 | /// - nodeID: 0
48 | ///
49 | void SerialPacket::begin()
50 | {
51 | begin (DEFAULT_BAUDRATE,0);
52 | }
53 |
54 | ///
55 | /// Begin using custom settings
56 | ///
57 | void SerialPacket::begin(long speed, uint8_t nodeID)
58 | {
59 | Serial.begin(speed);
60 | setNodeID(nodeID);
61 | }
62 |
63 | ///
64 | /// Send a single command
65 | ///
66 | void SerialPacket::sendCommand(uint8_t commandID, uint8_t payload)
67 | {
68 | setPacketType(COMMAND);
69 | setCommandID(commandID);
70 | sendPacket(payload);
71 | }
72 |
73 | ///
74 | /// Send a single command, reuses commandID from previous packets
75 | ///
76 | void SerialPacket::sendCommand(uint8_t payload)
77 | {
78 | setPacketType(COMMAND);
79 | sendPacket(payload);
80 | }
81 |
82 | ///
83 | /// Send a reply to a command
84 | ///
85 | void SerialPacket::sendCommandReply(uint8_t commandID, uint8_t payload)
86 | {
87 | setPacketType(COMMAND_REPLY);
88 | setCommandID(commandID);
89 | sendPacket(payload);
90 | }
91 |
92 | ///
93 | /// Request a single data value
94 | ///
95 | void SerialPacket::sendDataRequest(uint8_t sensorID, uint8_t payload)
96 | {
97 | setPacketType(DATA_REQUEST);
98 | setSensorID(sensorID);
99 | sendPacket(payload);
100 | }
101 |
102 | ///
103 | /// Request an array of data values
104 | ///
105 | void SerialPacket::sendDataArrayRequest(uint8_t arrayID, uint8_t payload)
106 | {
107 | setPacketType(DATA_ARRAY_REQUEST);
108 | setSensorID(arrayID);
109 | sendPacket(payload);
110 | }
111 |
112 | ///
113 | /// Send a single data value
114 | ///
115 | void SerialPacket::sendData(uint8_t sensorID, uint8_t payload)
116 | {
117 | setPacketType(DATA_BYTE);
118 | setSensorID(sensorID);
119 | sendPacket(payload);
120 | }
121 |
122 | ///
123 | /// Send a single data value
124 | ///
125 | void SerialPacket::sendData(uint8_t sensorID, int16_t payload)
126 | {
127 | setPacketType(DATA_INT);
128 | setSensorID(sensorID);
129 | sendPacket(payload);
130 | }
131 |
132 | ///
133 | /// Send a single 8-bit data value (Arduino 'byte' type), reuses sensorID from previous packets
134 | ///
135 | void SerialPacket::sendData(uint8_t payload)
136 | {
137 | setPacketType(DATA_BYTE);
138 | sendPacket(payload);
139 | }
140 |
141 | ///
142 | /// Send a single 16-bit data value (Arduino 'int' type), reuses sensorID from previous packets
143 | ///
144 | void SerialPacket::sendData(int16_t payload)
145 | {
146 | setPacketType(DATA_INT);
147 | sendPacket(payload);
148 | }
149 |
150 | ///
151 | /// Send out the actual 8-bit data packet (called from other 'send' functions)
152 | ///
153 | void SerialPacket::sendPacket(uint8_t& payload)
154 | {
155 | Serial.print("T");
156 | hexPrinting(_packetType);
157 | Serial.print("N");
158 | hexPrinting(_nodeID);
159 | Serial.print("I");
160 | if ((_packetType == COMMAND) | (_packetType == COMMAND_REPLY)) {
161 | hexPrinting(_commandID);
162 | _parity=_packetType^_nodeID^_commandID^payload;
163 | }
164 | else if ((_packetType == DATA_ARRAY_REQUEST) | (_packetType == DATA_BYTE) | (_packetType == DATA_REQUEST)) {
165 | hexPrinting(_sensorID);
166 | _parity=_packetType^_nodeID^_sensorID^payload;
167 | }
168 | Serial.print("P");
169 | hexPrinting(payload);
170 | Serial.print("Q");
171 | hexPrinting(_parity);
172 | Serial.println("");
173 | }
174 |
175 | ///
176 | /// Send out the actual 16-bit data packet (called from other 'send' functions)
177 | ///
178 | void SerialPacket::sendPacket(int16_t& payload)
179 | {
180 | _parity=_packetType^_nodeID^_sensorID^payload;
181 | Serial.print("T");
182 | hexPrinting(_packetType);
183 | Serial.print("N");
184 | hexPrinting(_nodeID);
185 | Serial.print("I");
186 | if ((_packetType == COMMAND) | (_packetType == COMMAND_REPLY)) {
187 | hexPrinting(_commandID);
188 | }
189 | //_packetType == DATA_ARRAY_REQUEST (not yet implemented as a separate function)
190 | else if ((_packetType == DATA_ARRAY_REQUEST) | (_packetType == DATA_INT) | (_packetType == DATA_REQUEST)) {
191 | hexPrinting(_sensorID);
192 | }
193 | Serial.print("P");
194 | hexPrinting(payload);
195 | Serial.print("Q");
196 | hexPrinting(_parity);
197 | Serial.println("");
198 | }
199 |
200 | ///
201 | /// Send multiple data samples in one packet by passing an array and its length
202 | ///
203 | void SerialPacket::sendDataArray(uint8_t *dataArray, uint8_t length)
204 | {
205 | setSensorID(length); //sensorID contains the length of the data array (can be used at receiving side)
206 | _parity=_packetType^_nodeID^_sensorID;
207 | Serial.print("T");
208 | hexPrinting(_packetType);
209 | Serial.print("N");
210 | hexPrinting(_nodeID);
211 | Serial.print("I");
212 | hexPrinting(_sensorID);
213 | Serial.print("P");
214 |
215 | for(int i=0 ; i
225 | /// Set commandID
226 | ///
227 | void SerialPacket::setCommandID(uint8_t& commandID)
228 | {
229 | _commandID=commandID;
230 | }
231 |
232 | ///
233 | /// Set packet type
234 | ///
235 | void SerialPacket::setPacketType(uint8_t type)
236 | {
237 | _packetType=type;
238 | }
239 |
240 | ///
241 | /// HexPrinting: helper function to print data with a constant field width (2 hex values)
242 | ///
243 | void SerialPacket::hexPrinting(uint8_t& data)
244 | {
245 | if(data<16) {
246 | Serial.print(0, HEX);
247 | }
248 | Serial.print(data, HEX);
249 | }
250 |
251 | ///
252 | /// HexPrinting: helper function to print data with a constant field width (2 hex values)
253 | ///
254 | void SerialPacket::hexPrinting(int16_t& data)
255 | {
256 | if(data<4096 && data>0) {
257 | Serial.print(0, HEX);
258 | }
259 | if(data<256 && data>0) {
260 | Serial.print(0, HEX);
261 | }
262 | if(data<16 && data>0) {
263 | Serial.print(0, HEX);
264 | }
265 | Serial.print(uint16_t(data), HEX); //casting to suppress FFFF for negative int values
266 | }
267 |
268 | ///
269 | /// Set nodeID
270 | ///
271 | void SerialPacket::setNodeID(uint8_t& nodeID)
272 | {
273 | _nodeID=nodeID;
274 | }
275 |
276 | ///
277 | /// Set sensorID
278 | ///
279 | void SerialPacket::setSensorID(uint8_t& sensorID)
280 | {
281 | _sensorID=sensorID;
282 | }
283 |
284 | ///
285 | /// Set readSerialData
286 | ///
287 | boolean SerialPacket::readSerialData()
288 | {
289 | while (Serial.available() && _inputChar[_incomingCounter] != '\n' ) {
290 | _inputChar[_incomingCounter]=(char)Serial.read();
291 | _incomingCounter++;
292 | // This checks for a minimum lenght (longer is also ok.. problem?)
293 | if (_incomingCounter == 16) {
294 | newPacket = true;
295 | }
296 | }
297 |
298 | //Flush buffer
299 | while (Serial.read() >= 0){}
300 |
301 | // parseSerialData();
302 | // Does not work when parsing is called in the return statement
303 | _incomingCounter=0;
304 | return (parseSerialData());
305 | }
306 |
307 | ///
308 | /// Set parseSerialData
309 | ///
310 | /// @todo: error handling: illegal payloads is now handled by char position (G2 -> 02, 2G -> 20, GG -> 00), requires hextodec reimplementation (when HEX_DEC_ERROR=0)
311 | boolean SerialPacket::parseSerialData()
312 | {
313 | incomingPacket.packetType = hex_to_dec(_inputChar[1])*16 + hex_to_dec(_inputChar[2]);
314 |
315 | incomingPacket.nodeID = hex_to_dec(_inputChar[4])*16 + hex_to_dec(_inputChar[5]);
316 | incomingPacket.payload = hex_to_dec(_inputChar[10])*16 + hex_to_dec(_inputChar[11]);
317 | // casting error hex vs decimal (in if)
318 | if ((incomingPacket.packetType == COMMAND) | (incomingPacket.packetType == COMMAND_REPLY)) {
319 | //Serial.println("parseSerialData");
320 | incomingPacket.commandID = hex_to_dec(_inputChar[7])*16 + hex_to_dec(_inputChar[8]);
321 | //Serial.println(incomingPacket.commandID);
322 | _checkedParity = incomingPacket.packetType^incomingPacket.nodeID^incomingPacket.commandID^incomingPacket.payload;
323 | }
324 | else if ((incomingPacket.packetType == DATA_INT) | (incomingPacket.packetType == DATA_BYTE) | (incomingPacket.packetType == DATA_REQUEST)) {
325 | incomingPacket.sensorID = hex_to_dec(_inputChar[7])*16 + hex_to_dec(_inputChar[8]);;
326 | _checkedParity = incomingPacket.packetType^incomingPacket.nodeID^incomingPacket.sensorID^incomingPacket.payload;
327 | }
328 | incomingPacket.parity = hex_to_dec(_inputChar[13])*16 + hex_to_dec(_inputChar[14]);
329 |
330 | #ifdef DEBUG_SERIAL
331 | printInfo();
332 | #endif
333 |
334 | if (newPacket) {
335 | newPacket=false;
336 | return checkParity();
337 | }
338 | else {
339 | return false;
340 | }
341 | }
342 |
343 | ///
344 | /// Check if all the field in the packet have acceptable value
345 | /// @TODO: implement this
346 | ///
347 | boolean SerialPacket::validatePacketFields()
348 | {
349 | if (true){
350 | return true;
351 | }
352 | else{
353 | return false;
354 | }
355 | }
356 |
357 |
358 | ///
359 | /// Convert HEX to Decimal
360 | ///
361 | #define HEX_DEC_ERROR 0
362 | uint8_t SerialPacket::hex_to_dec(uint8_t in)
363 | {
364 | if(((in >= '0') && (in <= '9'))) return in-'0';
365 | in |= 0x20;
366 | if(((in >= 'a') && (in <= 'f'))) return in-'a' + 10;
367 | return HEX_DEC_ERROR;
368 | }
369 |
370 | ///
371 | /// printInfo:
372 | ///
373 | void SerialPacket::printInfo()
374 | {
375 | Serial.print("Type: ");
376 | Serial.println(incomingPacket.packetType,HEX);
377 | Serial.print("NodeID: ");
378 | Serial.println(incomingPacket.nodeID,HEX);
379 | Serial.print("SensorID: ");
380 | Serial.println(incomingPacket.sensorID,HEX);
381 | Serial.print("CommandID ");
382 | Serial.println(incomingPacket.commandID,HEX);
383 | Serial.print("Payload: ");
384 | Serial.println(incomingPacket.payload,HEX);
385 | Serial.print("Parity: ");
386 | Serial.println(incomingPacket.parity,HEX);
387 | Serial.println("------------");
388 | Serial.print("Checked parity: ");
389 | Serial.println(_checkedParity,HEX);
390 | Serial.println("------------");
391 | }
392 |
393 | ///
394 | /// Check parity
395 | ///
396 | boolean SerialPacket::checkParity()
397 | {
398 | if (_checkedParity == incomingPacket.parity){
399 | #ifdef DEBUG_SERIAL
400 | Serial.println("Parity ok");
401 | Serial.println("----------------");
402 | #endif
403 | return true;
404 | }
405 | else{
406 | #ifdef DEBUG_SERIAL
407 | Serial.println("Parity wrong");
408 | #endif
409 | return false;
410 | }
411 | }
412 |
413 | ///
414 | /// Get commandID
415 | ///
416 | uint8_t SerialPacket::getCommandID()
417 | {
418 | return incomingPacket.commandID;
419 | }
420 |
421 | ///
422 | /// Get getPayload
423 | ///
424 | uint8_t SerialPacket::getPayload()
425 | {
426 | return incomingPacket.payload;
427 | }
--------------------------------------------------------------------------------
/SerialPacket/SerialPacket.h:
--------------------------------------------------------------------------------
1 | // SerialPacket.h - Library for sending serial data packets
2 | // Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
3 | //
4 | // Version History:
5 | // Version 0.1: Send single data sample in a packet
6 | // Version 0.2: Send arrays with multiple samples in a packet
7 | // Version 0.3: Conditional compilation: SERIAL_ASCII vs SERIAL_BINARY (includes.h)
8 | // Version 0.4: hexPrinting helper, changed packet types, commandID/packet
9 | // Version 0.5: added 'sendCommand', 'sendData', ... functions (replacing the generic 'sendPacket')
10 | // removed condition compilation from v0.3
11 | // shortened serial ASCII messages ('Type' -> 'T', 'NodeID' -> 'N')
12 | // Version 0.6: Added support for packets with 16-bit payload (renamed packet types -> hex values)
13 | // Added "dataArrayRequest" packet
14 | // Version 0.7: processing incoming packets
15 | // Roadmap:
16 | // Version 0.7: send 16-bit data arrays
17 | // Separate classes for commands vs data packets?
18 | // Version 0.8: ??
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 |
34 | #ifndef SerialPacket_h
35 | #define SerialPacket_h
36 | #include
37 |
38 | class SerialPacket
39 | {
40 | public:
41 | SerialPacket();
42 |
43 | void begin();
44 | void begin(long speed, uint8_t nodeID);
45 |
46 | void sendCommand(uint8_t commandID, uint8_t payload);
47 | void sendCommand(uint8_t payload);
48 | void sendCommandReply(uint8_t commandID, uint8_t payload);
49 |
50 | void sendDataRequest(uint8_t sensorID, uint8_t payload);
51 | void sendData(uint8_t sensorID, uint8_t payload);
52 | void sendData(uint8_t sensorID, int16_t payload);
53 |
54 | void sendData(uint8_t payload);
55 | void sendData(int16_t payload);
56 |
57 | void sendDataArrayRequest(uint8_t arrayID, uint8_t length);
58 | void sendDataArray(uint8_t *dataArray, uint8_t length);
59 |
60 | boolean readSerialData();
61 | uint8_t getCommandID();
62 | uint8_t getPayload();
63 |
64 | private:
65 | struct packet
66 | {
67 | uint8_t packetType;
68 | uint8_t nodeID;
69 | uint8_t sensorID;
70 | uint8_t commandID;
71 | uint8_t payload;
72 | uint8_t parity;
73 | } incomingPacket, outgoingPacket; //TODO: also use this struct to send packets? (todo underscore)
74 |
75 | uint8_t _packetType;
76 | uint8_t _nodeID;
77 | uint8_t _sensorID;
78 | uint8_t _commandID;
79 | uint8_t _parity;
80 | uint8_t _checkedParity;
81 |
82 | boolean _inComingPacketComplete;
83 | char _inputChar[20];
84 | uint8_t _incomingCounter;
85 |
86 | void sendPacket(uint8_t& payload);
87 | void sendPacket(int16_t& payload);
88 | void setPacketType(uint8_t type);
89 | void setCommandID(uint8_t& commandID);
90 | void setSensorID(uint8_t& sensorID);
91 | void setNodeID(uint8_t& nodeID);
92 | void hexPrinting(uint8_t& data);
93 | void hexPrinting(int16_t& data);
94 | uint8_t hex_to_dec(uint8_t in);
95 | boolean parseSerialData();
96 | void printInfo();
97 | boolean checkParity();
98 | boolean newPacket;
99 | boolean validatePacketFields();
100 | };
101 | #endif
102 |
--------------------------------------------------------------------------------
/SerialPacket/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ##
3 | # build.sh - Script to build several Arduino .ino files at the same time
4 | # 1. Build the source
5 | # 2. Static code analysis using cppcheck
6 | # 3. Fix indentation using bcpp
7 | #
8 | # Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
9 | #
10 | # This program is free software; you can redistribute it and/or
11 | # modify it under the terms of the GNU Lesser General Public
12 | # License as published by the Free Software Foundation; either
13 | # version 2.1 of the License, or (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | # Lesser General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU Lesser General Public
21 | # License along with this program; if not, write to the Free Software
22 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 |
24 | START=$(date +%s)
25 | START2=$(date)
26 |
27 | ##################################################################
28 | # SCRIPT SETTINGS #
29 | ##################################################################
30 |
31 | SCRIPTPATH="`pwd`"
32 | RESOURCESPATH=$SCRIPTPATH"/resources/"
33 | EXAMPLESPATH=$SCRIPTPATH"/examples/"
34 | CPPCHECKOPTIONS="--enable=all --error-exitcode=1 --std=c99 --std=posix --std=c++11 -v"
35 |
36 | BUILDSUCCESCOUNTER=0
37 | BUILDFAILURECOUNTER=0
38 |
39 | CODECHECKFAILURECOUNTER=0
40 | CODECHECKSUCCESCOUNTER=0
41 |
42 | INDENTSUCCESCOUNTER=0
43 | INDENTFAILURECOUNTER=0
44 |
45 | MAXDEPTH=1
46 |
47 | ##################################################################
48 | # SELECT FILES TO BUILD #
49 | ##################################################################
50 |
51 | cd examples
52 |
53 | # create the FILES[] array, filled with all the folder names in the examples folder
54 | FILES=( $(find . -maxdepth 2 -type d -printf '%P\n') )
55 |
56 | # select the range of file you want to build (from FIRSTFILE up to LASTFILE)
57 | FIRSTFILE=0
58 | LASTFILE=${#FILES[@]}-1 #equals last element of the FILES[] array
59 |
60 | ##################################################################
61 | # FUNCTIONS #
62 | ##################################################################
63 |
64 | function buildFile
65 | {
66 | scons > /dev/null
67 | if [ $? -eq 0 ]
68 | then
69 | echo "Build OK in folder: '`pwd | awk -F/ '{print $(NF-1),$NF}'`' "
70 | echo "`date`: Build OK in folder: '`pwd | awk -F/ '{print $(NF-1),$NF}'`' " >> $RESOURCESPATH/succes.log
71 | let BUILDSUCCESCOUNTER++
72 |
73 | else
74 | echo "Build errors in folder: '`pwd | awk -F/ '{print $(NF-1),$NF}'`' "
75 | echo "`date`: Build errors in folder: '`pwd | awk -F/ '{print $(NF-1),$NF}'`' " >> $RESOURCESPATH/errors.log
76 | let BUILDFAILURECOUNTER++
77 | fi
78 | }
79 |
80 | function CreateLogfiles
81 | {
82 | if [ -f $RESOURCESPATH/succes.log ];
83 | then
84 | echo -ne ""
85 | else
86 | echo "File succes.log does not exist, creating it now"
87 | touch $RESOURCESPATH/succes.log
88 | fi
89 |
90 | if [ -f $RESOURCESPATH/errors.log ];
91 | then
92 | echo -ne ""
93 | else
94 | echo "File errors.log does not exist, creating it now"
95 | touch $RESOURCESPATH/errors.log
96 | fi
97 | }
98 |
99 | function PrintStats
100 | {
101 | echo ""
102 | echo "------------------------------"
103 | echo "| Succesfull builds : $BUILDSUCCESCOUNTER "
104 | echo "| Failed builds : $BUILDFAILURECOUNTER "
105 | echo "|-----------------------------"
106 | echo "| Succesfull code checks : $CODECHECKSUCCESCOUNTER "
107 | echo "| Failed code checks : $CODECHECKFAILURECOUNTER "
108 | echo "|-----------------------------"
109 | echo "| Succesfull indents : $INDENTSUCCESCOUNTER "
110 | echo "| Failed indents : $INDENTFAILURECOUNTER "
111 | echo "------------------------------"
112 | echo ""
113 | }
114 |
115 | function logStats
116 | {
117 | echo "--------------------------------" > $RESOURCESPATH/lastbuild.log
118 | echo "| `date` |" >> $RESOURCESPATH/lastbuild.log
119 | echo "--------------------------------" >> $RESOURCESPATH/lastbuild.log
120 | echo "| Succesfull builds : $BUILDSUCCESCOUNTER |" >> $RESOURCESPATH/lastbuild.log
121 | echo "| Failed builds : $BUILDFAILURECOUNTER |" >> $RESOURCESPATH/lastbuild.log
122 | echo "|------------------------------|" >> $RESOURCESPATH/lastbuild.log
123 | echo "| Succesfull code checks : $CODECHECKSUCCESCOUNTER |" >> $RESOURCESPATH/lastbuild.log
124 | echo "| Failed code checks : $CODECHECKFAILURECOUNTER |" >> $RESOURCESPATH/lastbuild.log
125 | echo "--------------------------------" >> $RESOURCESPATH/lastbuild.log
126 |
127 | END=$(date +%s)
128 | DIFF=$(( $END - $START ))
129 | echo "Build took $DIFF seconds." >> $RESOURCESPATH/lastbuild.log
130 | echo "Build took $DIFF seconds."
131 | }
132 |
133 | function buildFiles
134 | {
135 | for ((i=FIRSTFILE;i<=LASTFILE;i++)); do
136 | echo ${FILES[i]} | grep build > /dev/null # don't try a scons build in the build folder
137 | if [ $? -eq 1 ]
138 | then
139 | cd ${FILES[i]}
140 | if [ -f *.ino ]; # to ignore (toplevel) folders without .ino files
141 | then
142 | buildFile
143 | fi
144 | cd $EXAMPLESPATH
145 | fi
146 | done
147 | }
148 |
149 | function staticCodeCheck
150 | {
151 | if [ $BUILDFAILURECOUNTER -eq 0 ]
152 | then
153 | staticCodeCheckRun
154 | else
155 | echo "Build errors -> skipping static code analysis"
156 | fi
157 | }
158 |
159 | function staticCodeCheckRun
160 | {
161 | FILES=( $(find . -maxdepth 3 -type d -printf '%P\n') )
162 | for ((i=FIRSTFILE;i<=LASTFILE;i++)); do
163 | cd ${FILES[i]}
164 | if [ -f *.ino ]; # to ignore (toplevel) folders without .ino files
165 | then
166 | staticCodeCheckFile
167 | fi
168 | cd $EXAMPLESPATH
169 | done
170 |
171 | cd $SCRIPTPATH
172 | cppcheck $CPPCHECKOPTIONS *.h > /dev/null
173 | if [ $? -eq 0 ]
174 | then
175 | echo "Cppcheck OK in header file(s)"
176 | echo "`date`: Cppcheck OK in header file(s)" >> $RESOURCESPATH/succes.log
177 | let CODECHECKSUCCESCOUNTER++
178 |
179 | else
180 | echo "Cppcheck errors in header file(s)"
181 | echo "`date`: Cppcheck errors in header file(s)" >> $RESOURCESPATH/errors.log
182 | let CODECHECKFAILURECOUNTER++
183 | fi
184 |
185 | cppcheck $CPPCHECKOPTIONS *.cpp > /dev/null
186 | if [ $? -eq 0 ]
187 | then
188 | echo "Cppcheck OK in cpp file(s)"
189 | echo "`date`: Cppcheck OK in cpp file(s)" >> $RESOURCESPATH/succes.log
190 | let CODECHECKSUCCESCOUNTER++
191 |
192 | else
193 | echo "Cppcheck errors in cpp file(s)"
194 | echo "`date`: Cppcheck errors in cpp file(s)" >> $RESOURCESPATH/errors.log
195 | let CODECHECKFAILURECOUNTER++
196 | fi
197 | }
198 |
199 | function staticCodeCheckFile
200 | {
201 | if [ -f *.cpp ]; # to ignore (toplevel) folders without .cpp files
202 | then
203 | cppcheck $CPPCHECKOPTIONS *.cpp > /dev/null
204 | if [ $? -eq 0 ]
205 | then
206 | echo "Cppcheck OK in folder: '`pwd | awk -F/ '{print $NF}'`' "
207 | echo "`date`: Cppcheck OK in folder: '`pwd | awk -F/ '{print $NF}'`' " >> $RESOURCESPATH/succes.log
208 | let CODECHECKSUCCESCOUNTER++
209 |
210 | else
211 | echo "Cppcheck errors in folder: '`pwd | awk -F/ '{print $NF}'`' "
212 | echo "`date`: Cppcheck errors in folder: '`pwd | awk -F/ '{print $NF}'`' " >> $RESOURCESPATH/errors.log
213 | let CODECHECKFAILURECOUNTER++
214 | fi
215 | fi
216 | }
217 |
218 | function indentFiles
219 | {
220 | if [ $BUILDFAILURECOUNTER -eq 0 ]
221 | then
222 | indentFilesRun
223 | else
224 | echo "Build errors -> skipping code indenter"
225 | fi
226 | }
227 |
228 | function indentFilesRun
229 | {
230 | filesuffix="h"
231 | indentFilesType
232 | filesuffix="cpp"
233 | indentFilesType
234 | filesuffix="ino"
235 | MAXDEPTH=5
236 | indentFilesType
237 | }
238 |
239 | function indentFilesType
240 | {
241 | file_list=`find -maxdepth $MAXDEPTH ${1} -name "*.${filesuffix}" -type f`
242 | for file2indent in $file_list
243 | do
244 | echo "Indenting file $file2indent"
245 | bcpp -fi "$file2indent" -fnc $RESOURCESPATH/"bcpp_indenter.cfg" -fo indentoutput.tmp
246 | if [ $? -eq 0 ]
247 | then
248 | let INDENTSUCCESCOUNTER++
249 | else
250 | let INDENTFAILURECOUNTER++
251 | fi
252 | mv indentoutput.tmp "$file2indent"
253 | done
254 | }
255 |
256 | function cleanPreviousBuilds
257 | {
258 | ls | grep .elf > /dev/null
259 | if [ $? -eq 0 ]
260 | then
261 | rm *.elf
262 | fi
263 |
264 | ls | grep .hex > /dev/null
265 | if [ $? -eq 0 ]
266 | then
267 | rm *.hex
268 | fi
269 |
270 | ls | grep build > /dev/null
271 | if [ $? -eq 0 ]
272 | then
273 | rm -rf build
274 | fi
275 |
276 | ls -lah | grep .sconsign.dblite > /dev/null
277 | if [ $? -eq 0 ]
278 | then
279 | rm .sconsign.dblite
280 | fi
281 |
282 | ls -lah | grep "~" > /dev/null
283 | if [ $? -eq 0 ]
284 | then
285 | rm *~
286 | fi
287 | }
288 |
289 | function cleanFiles
290 | {
291 | for ((i=FIRSTFILE;i<=LASTFILE;i++)); do
292 | echo ${FILES[i]} | grep build > /dev/null # don't try a clean in the build folder
293 | if [ $? -eq 1 ]
294 | then
295 | cd ${FILES[i]}
296 | echo "Cleaning: ${FILES[i]}"
297 | cleanPreviousBuilds
298 | fi
299 | cd $EXAMPLESPATH
300 | done
301 | }
302 |
303 | ##################################################################
304 | # MAIN CODE STARTS HERE #
305 | ##################################################################
306 |
307 | if [ "$1" = "clean" ]
308 | then
309 | cleanFiles
310 | else
311 | CreateLogfiles
312 | buildFiles
313 | staticCodeCheck
314 | indentFiles
315 | PrintStats
316 | logStats
317 | fi
--------------------------------------------------------------------------------
/SerialPacket/defines.h:
--------------------------------------------------------------------------------
1 | // Select either ASCII or the normal binary serial packet type
2 |
3 | #define SERIAL_ASCII
4 | //#define SERIAL_BINARY
5 |
6 | //#define DEBUG_SERIAL
7 |
8 |
9 | #define DEFAULT_BAUDRATE 115200
10 |
11 | #define COMMAND 0x01
12 | #define COMMAND_REPLY 0x02
13 |
14 | #define DATA_REQUEST 0x11
15 | #define DATA_BYTE 0x12
16 | #define DATA_INT 0x13
17 |
18 | #define DATA_ARRAY_REQUEST 0x21
19 | #define DATA_ARRAY 0x22
20 |
21 | /// Sensor Types:
22 |
23 | #define TEMPERATURE 0x10
24 | #define HUMIDITY 0x11
25 |
26 | #define DISTANCE 0x30
27 | #define MOTORSTATUS 0x50
28 |
29 | /// Command IDs
30 |
31 | #define STOP_MOTOR_A 0x10
32 | #define START_MOTOR_A 0x11
33 | #define SET_SPEED_MOTOR_A 0x12
34 | #define BRAKE_MOTOR_A 0x13
35 |
36 | #define STOP_MOTOR_B 0x15
37 | #define START_MOTOR_B 0x16
38 | #define SET_SPEED_MOTOR_B 0x17
39 | #define BRAKE_MOTOR_B 0x18
40 |
--------------------------------------------------------------------------------
/SerialPacket/defines.h.orig:
--------------------------------------------------------------------------------
1 | // Select either ASCII or the normal binary serial packet type
2 |
3 | #define SERIAL_ASCII
4 | //#define SERIAL_BINARY
5 |
6 | #define COMMAND 0x01
7 | #define COMMAND_REPLY 0x02
8 |
9 | #define DATA_REQUEST 0x11
10 | #define DATA_BYTE 0x12
11 | #define DATA_INT 0x13
12 |
13 | #define DATA_ARRAY_REQUEST 0x21
14 | #define DATA_ARRAY 0x22
15 |
16 | /// Sensor Types:
17 |
18 | #define TEMPERATURE 0x10
19 | #define HUMIDITY 0x11
20 |
21 | #define DISTANCE 0x30
22 |
23 | /// Command IDs
24 |
25 | #define STOP_MOTOR_A 0x10
26 | #define START_MOTOR_A 0x11
27 | #define SET_SPEED_MOTOR_A 0x12
28 | #define BRAKE_MOTOR_A 0x13
29 |
30 | #define STOP_MOTOR_B 0x15
31 | #define START_MOTOR_B 0x16
32 | #define SET_SPEED_MOTOR_B 0x17
33 | #define BRAKE_MOTOR_B 0x18
34 |
--------------------------------------------------------------------------------
/SerialPacket/examples/ArduinoActions/ArduinoActions.ino:
--------------------------------------------------------------------------------
1 | // ReceivePackets.ino - Demo application to receive data and command messages
2 | // Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
3 | //
4 | // Warning: this code is untested (it compiles, but not tested on hardware)
5 |
6 | #include "SerialPacket.h"
7 | #include "defines.h"
8 |
9 | SerialPacket Packet;
10 |
11 | void setup()
12 | {
13 | Packet.begin(115200,0); //begin(speed,nodeID);
14 | }
15 |
16 | void loop()
17 | {
18 | delay(500);
19 | }
20 |
21 | /*
22 | SerialEvent occurs whenever a new data comes in the
23 | hardware serial RX. This routine is run between each
24 | time loop() runs, so using delay inside loop can delay
25 | response. Multiple bytes of data may be available.
26 | */
27 |
28 | void serialEvent()
29 | {
30 | Packet.readSerialData();
31 | serialActions();
32 | }
33 |
34 | /// Take Actions based on incoming commands:
35 | void serialActions(){
36 | Serial.println("Starting serialActions");
37 |
38 | if (Packet.getCommandID() == SET_SPEED_MOTOR_A) {
39 | int motorSpeed = Packet.getPayload();
40 | Serial.println("Set the motor speed to value 'motorSpeed'");
41 | Packet.sendData(COMMAND_REPLY,uint8_t(SET_SPEED_MOTOR_A));
42 | }
43 | }
--------------------------------------------------------------------------------
/SerialPacket/examples/ArduinoActions/SConstruct:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | # scons script for the Arduino sketch
4 | # http://github.com/suapapa/arscons
5 | #
6 | # Copyright (C) 2010-2012 by Homin Lee
7 | #
8 | # This program is free software; you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation; either version 3 of the License, or
11 | # (at your option) any later version.
12 |
13 | # You'll need the serial module: http://pypi.python.org/pypi/pyserial
14 |
15 | # Basic Usage:
16 | # 1. make a folder which have same name of the sketch (ex. Blink/ for Blink.pde)
17 | # 2. put the sketch and SConstruct(this file) under the folder.
18 | # 3. to make the HEX. do following in the folder.
19 | # $ scons
20 | # 4. to upload the binary, do following in the folder.
21 | # $ scons upload
22 |
23 | # Thanks to:
24 | # * Ovidiu Predescu and Lee Pike
25 | # for Mac port and bugfix.
26 | #
27 | # This script tries to determine the port to which you have an Arduino
28 | # attached. If multiple USB serial devices are attached to your
29 | # computer, you'll need to explicitly specify the port to use, like
30 | # this:
31 | #
32 | # $ scons ARDUINO_PORT=/dev/ttyUSB0
33 | #
34 | # To add your own directory containing user libraries, pass EXTRA_LIB
35 | # to scons, like this:
36 | #
37 | # $ scons EXTRA_LIB=
38 | #
39 |
40 | from glob import glob
41 | from itertools import ifilter, imap
42 | from subprocess import check_call, CalledProcessError
43 | import sys
44 | import re
45 | import os
46 | from os import path
47 | from pprint import pprint
48 |
49 | env = Environment()
50 | platform = env['PLATFORM']
51 |
52 | VARTAB = {}
53 |
54 | def resolve_var(varname, default_value):
55 | global VARTAB
56 | # precedence: scons argument -> environment variable -> default value
57 | ret = ARGUMENTS.get(varname, None)
58 | VARTAB[varname] = ('arg', ret)
59 | if ret == None:
60 | ret = os.environ.get(varname, None)
61 | VARTAB[varname] = ('env', ret)
62 | if ret == None:
63 | ret = default_value
64 | VARTAB[varname] = ('dfl', ret)
65 | return ret
66 |
67 | def getUsbTty(rx):
68 | usb_ttys = glob(rx)
69 | return usb_ttys[0] if len(usb_ttys) == 1 else None
70 |
71 | AVR_BIN_PREFIX = None
72 | AVRDUDE_CONF = None
73 |
74 | if platform == 'darwin':
75 | # For MacOS X, pick up the AVR tools from within Arduino.app
76 | ARDUINO_HOME = resolve_var('ARDUINO_HOME',
77 | '/Applications/Arduino.app/Contents/Resources/Java')
78 | ARDUINO_PORT = resolve_var('ARDUINO_PORT', getUsbTty('/dev/tty.usbserial*'))
79 | SKETCHBOOK_HOME = resolve_var('SKETCHBOOK_HOME', '')
80 | AVR_HOME = resolve_var('AVR_HOME',
81 | path.join(ARDUINO_HOME, 'hardware/tools/avr/bin'))
82 | elif platform == 'win32':
83 | # For Windows, use environment variables.
84 | ARDUINO_HOME = resolve_var('ARDUINO_HOME', None)
85 | ARDUINO_PORT = resolve_var('ARDUINO_PORT', '')
86 | SKETCHBOOK_HOME = resolve_var('SKETCHBOOK_HOME', '')
87 | AVR_HOME = resolve_var('AVR_HOME',
88 | path.join(ARDUINO_HOME, 'hardware/tools/avr/bin'))
89 | else:
90 | # For Ubuntu Linux (9.10 or higher)
91 | ARDUINO_HOME = resolve_var('ARDUINO_HOME', '/usr/share/arduino/')
92 | ARDUINO_PORT = resolve_var('ARDUINO_PORT', getUsbTty('/dev/ttyUSB*'))
93 | SKETCHBOOK_HOME = resolve_var('SKETCHBOOK_HOME',
94 | path.expanduser('~/share/arduino/sketchbook/'))
95 | AVR_HOME = resolve_var('AVR_HOME', '')
96 |
97 |
98 | ARDUINO_BOARD = resolve_var('ARDUINO_BOARD', 'atmega328')
99 | ARDUINO_VER = resolve_var('ARDUINO_VER', 0) # Default to 0 if nothing is specified
100 | RST_TRIGGER = resolve_var('RST_TRIGGER', None) # use built-in pulseDTR() by default
101 | EXTRA_LIB = resolve_var('EXTRA_LIB', None) # handy for adding another arduino-lib dir
102 |
103 | pprint(VARTAB, indent = 4)
104 |
105 | if not ARDUINO_HOME:
106 | print 'ARDUINO_HOME must be defined.'
107 | raise KeyError('ARDUINO_HOME')
108 |
109 | ARDUINO_CONF = path.join(ARDUINO_HOME, 'hardware/arduino/boards.txt')
110 | # check given board name, ARDUINO_BOARD is valid one
111 | arduino_boards = path.join(ARDUINO_HOME,'hardware/*/boards.txt')
112 | custom_boards = path.join(SKETCHBOOK_HOME,'hardware/*/boards.txt')
113 | board_files = glob(arduino_boards) + glob(custom_boards)
114 | ptnBoard = re.compile(r'^([^#]*)\.name=(.*)')
115 | boards = {}
116 | for bf in board_files:
117 | for line in open(bf):
118 | result = ptnBoard.match(line)
119 | if result:
120 | boards[result.group(1)] = (result.group(2), bf)
121 |
122 | if ARDUINO_BOARD not in boards:
123 | print "ERROR! the given board name, %s is not in the supported board list:" % ARDUINO_BOARD
124 | print "all available board names are:"
125 | for name, description in boards.iteritems():
126 | print "\t%s for %s" % (name.ljust(14), description[0])
127 | #print "however, you may edit %s to add a new board." % ARDUINO_CONF
128 | sys.exit(-1)
129 |
130 | ARDUINO_CONF = boards[ARDUINO_BOARD][1]
131 |
132 | def getBoardConf(conf, default = None):
133 | for line in open(ARDUINO_CONF):
134 | line = line.strip()
135 | if '=' in line:
136 | key, value = line.split('=')
137 | if key == '.'.join([ARDUINO_BOARD, conf]):
138 | return value
139 | ret = default
140 | if ret == None:
141 | print "ERROR! can't find %s in %s" % (conf, ARDUINO_CONF)
142 | assert(False)
143 | return ret
144 |
145 | ARDUINO_CORE = path.join(ARDUINO_HOME, path.dirname(ARDUINO_CONF),
146 | 'cores/', getBoardConf('build.core', 'arduino'))
147 | ARDUINO_SKEL = path.join(ARDUINO_CORE, 'main.cpp')
148 |
149 | if ARDUINO_VER == 0:
150 | arduinoHeader = path.join(ARDUINO_CORE, 'Arduino.h')
151 | print "No Arduino version specified. Discovered version",
152 | if path.exists(arduinoHeader):
153 | print "100 or above"
154 | ARDUINO_VER = 100
155 | else:
156 | print "0023 or below"
157 | ARDUINO_VER = 23
158 | else:
159 | print "Arduino version " + ARDUINO_VER + " specified"
160 |
161 | # Some OSs need bundle with IDE tool-chain
162 | if platform == 'darwin' or platform == 'win32':
163 | AVRDUDE_CONF = path.join(ARDUINO_HOME, 'hardware/tools/avr/etc/avrdude.conf')
164 |
165 | AVR_BIN_PREFIX = path.join(AVR_HOME, 'avr-')
166 |
167 | ARDUINO_LIBS = [path.join(ARDUINO_HOME, 'libraries')]
168 | if EXTRA_LIB:
169 | ARDUINO_LIBS.append(EXTRA_LIB)
170 | if SKETCHBOOK_HOME:
171 | ARDUINO_LIBS.append(path.join(SKETCHBOOK_HOME, 'libraries'))
172 |
173 |
174 | # Override MCU and F_CPU
175 | MCU = ARGUMENTS.get('MCU', getBoardConf('build.mcu'))
176 | F_CPU = ARGUMENTS.get('F_CPU', getBoardConf('build.f_cpu'))
177 |
178 | # There should be a file with the same name as the folder and
179 | # with the extension .pde or .ino
180 | TARGET = path.basename(path.realpath(os.curdir))
181 | assert(path.exists(TARGET + '.ino') or path.exists(TARGET + '.pde'))
182 | sketchExt = '.ino' if path.exists(TARGET + '.ino') else '.pde'
183 |
184 | cFlags = ['-ffunction-sections', '-fdata-sections', '-fno-exceptions',
185 | '-funsigned-char', '-funsigned-bitfields', '-fpack-struct',
186 | '-fshort-enums', '-Os', '-Wall', '-mmcu=%s' % MCU]
187 | envArduino = Environment(CC = AVR_BIN_PREFIX + 'gcc',
188 | CXX = AVR_BIN_PREFIX + 'g++',
189 | AS = AVR_BIN_PREFIX + 'gcc',
190 | CPPPATH = ['build/core'],
191 | CPPDEFINES = {'F_CPU': F_CPU, 'ARDUINO': ARDUINO_VER},
192 | CFLAGS = cFlags + ['-std=gnu99'],
193 | CCFLAGS = cFlags,
194 | ASFLAGS = ['-assembler-with-cpp','-mmcu=%s' % MCU],
195 | TOOLS = ['gcc','g++', 'as'])
196 |
197 | hwVariant = path.join(ARDUINO_HOME, 'hardware/arduino/variants',
198 | getBoardConf("build.variant", ""))
199 | if hwVariant:
200 | envArduino.Append(CPPPATH = hwVariant)
201 |
202 | def run(cmd):
203 | """Run a command and decipher the return code. Exit by default."""
204 | print ' '.join(cmd)
205 | try:
206 | check_call(cmd)
207 | except CalledProcessError as cpe:
208 | print "Error: return code: " + str(cpe.returncode)
209 | sys.exit(cpe.returncode)
210 |
211 | # WindowXP not supported path.samefile
212 | def sameFile(p1, p2):
213 | if platform == 'win32':
214 | ap1 = path.abspath(p1)
215 | ap2 = path.abspath(p2)
216 | return ap1 == ap2
217 | return path.samefile(p1, p2)
218 |
219 | def fnProcessing(target, source, env):
220 | wp = open(str(target[0]), 'wb')
221 | wp.write(open(ARDUINO_SKEL).read())
222 |
223 | types='''void
224 | int char word long
225 | float double byte long
226 | boolean
227 | uint8_t uint16_t uint32_t
228 | int8_t int16_t int32_t'''
229 | types=' | '.join(types.split())
230 | re_signature = re.compile(r"""^\s* (
231 | (?: (%s) \s+ )?
232 | \w+ \s*
233 | \( \s* ((%s) \s+ \*? \w+ (?:\s*,\s*)? )* \)
234 | ) \s* {? \s* $""" % (types, types), re.MULTILINE | re.VERBOSE)
235 |
236 | prototypes = {}
237 |
238 | for file in glob(path.realpath(os.curdir) + "/*" + sketchExt):
239 | for line in open(file):
240 | result = re_signature.search(line)
241 | if result:
242 | prototypes[result.group(1)] = result.group(2)
243 |
244 | for name in prototypes.iterkeys():
245 | print "%s;" % name
246 | wp.write("%s;\n" % name)
247 |
248 | for file in glob(path.realpath(os.curdir) + "/*" + sketchExt):
249 | print file, TARGET
250 | if not sameFile(file, TARGET + sketchExt):
251 | wp.write('#line 1 "%s"\r\n' % file)
252 | wp.write(open(file).read())
253 |
254 | # Add this preprocessor directive to localize the errors.
255 | sourcePath = str(source[0]).replace('\\', '\\\\')
256 | wp.write('#line 1 "%s"\r\n' % sourcePath)
257 | wp.write(open(str(source[0])).read())
258 |
259 | def fnCompressCore(target, source, env):
260 | core_prefix = 'build/core/'.replace('/', os.path.sep)
261 | core_files = (x for x in imap(str, source)
262 | if x.startswith(core_prefix))
263 | for file in core_files:
264 | run([AVR_BIN_PREFIX + 'ar', 'rcs', str(target[0]), file])
265 |
266 | bldProcessing = Builder(action = fnProcessing) #, suffix = '.cpp', src_suffix = sketchExt)
267 | bldCompressCore = Builder(action = fnCompressCore)
268 | bldELF = Builder(action = AVR_BIN_PREFIX + 'gcc -mmcu=%s ' % MCU +
269 | '-Os -Wl,--gc-sections -lm -o $TARGET $SOURCES -lc')
270 | bldHEX = Builder(action = AVR_BIN_PREFIX + 'objcopy -O ihex -R .eeprom $SOURCES $TARGET')
271 |
272 | envArduino.Append(BUILDERS = {'Processing' : bldProcessing})
273 | envArduino.Append(BUILDERS = {'CompressCore': bldCompressCore})
274 | envArduino.Append(BUILDERS = {'Elf' : bldELF})
275 | envArduino.Append(BUILDERS = {'Hex' : bldHEX})
276 |
277 | ptnSource = re.compile(r'\.(?:c(?:pp)?|S)$')
278 | def gatherSources(srcpath):
279 | return [path.join(srcpath, f) for f
280 | in os.listdir(srcpath) if ptnSource.search(f)]
281 |
282 | # add arduino core sources
283 | VariantDir('build/core', ARDUINO_CORE)
284 | core_sources = gatherSources(ARDUINO_CORE)
285 | core_sources = [x.replace(ARDUINO_CORE, 'build/core/') for x
286 | in core_sources if path.basename(x) != 'main.cpp']
287 |
288 | # add libraries
289 | libCandidates = []
290 | ptnLib = re.compile(r'^[ ]*#[ ]*include [<"](.*)\.h[>"]')
291 | for line in open(TARGET + sketchExt):
292 | result = ptnLib.search(line)
293 | if not result:
294 | continue
295 | # Look for the library directory that contains the header.
296 | filename = result.group(1) + '.h'
297 | for libdir in ARDUINO_LIBS:
298 | for root, dirs, files in os.walk(libdir, followlinks=True):
299 | if filename in files:
300 | libCandidates.append(path.basename(root))
301 |
302 | # Hack. In version 20 of the Arduino IDE, the Ethernet library depends
303 | # implicitly on the SPI library.
304 | if ARDUINO_VER >= 20 and 'Ethernet' in libCandidates:
305 | libCandidates.append('SPI')
306 |
307 | all_libs_sources = []
308 | for index, orig_lib_dir in enumerate(ARDUINO_LIBS):
309 | lib_dir = 'build/lib_%02d' % index
310 | VariantDir(lib_dir, orig_lib_dir)
311 | for libPath in ifilter(path.isdir, glob(path.join(orig_lib_dir, '*'))):
312 | libName = path.basename(libPath)
313 | if not libName in libCandidates:
314 | continue
315 | envArduino.Append(CPPPATH = libPath.replace(orig_lib_dir, lib_dir))
316 | lib_sources = gatherSources(libPath)
317 | utilDir = path.join(libPath, 'utility')
318 | if path.exists(utilDir) and path.isdir(utilDir):
319 | lib_sources += gatherSources(utilDir)
320 | envArduino.Append(CPPPATH = utilDir.replace(orig_lib_dir, lib_dir))
321 | lib_sources = (x.replace(orig_lib_dir, lib_dir) for x in lib_sources)
322 | all_libs_sources.extend(lib_sources)
323 |
324 | # Add raw sources which live in sketch dir.
325 | build_top = path.realpath('.')
326 | VariantDir('build/local/', build_top)
327 | local_sources = gatherSources(build_top)
328 | local_sources = [x.replace(build_top, 'build/local/') for x in local_sources]
329 | if local_sources:
330 | envArduino.Append(CPPPATH = 'build/local')
331 |
332 | # Convert sketch(.pde) to cpp
333 | envArduino.Processing('build/' + TARGET + '.cpp', 'build/' + TARGET + sketchExt)
334 | VariantDir('build', '.')
335 |
336 | sources = ['build/' + TARGET + '.cpp']
337 | #sources += core_sources
338 | sources += local_sources
339 | sources += all_libs_sources
340 |
341 | # Finally Build!!
342 | core_objs = envArduino.Object(core_sources)
343 | objs = envArduino.Object(sources) #, LIBS=libs, LIBPATH='.')
344 | objs = objs + envArduino.CompressCore('build/core.a', core_objs)
345 | envArduino.Elf(TARGET + '.elf', objs)
346 | envArduino.Hex(TARGET + '.hex', TARGET + '.elf')
347 |
348 | # Print Size
349 | # TODO: check binary size
350 | MAX_SIZE = getBoardConf('upload.maximum_size')
351 | print "maximum size for hex file: %s bytes" % MAX_SIZE
352 | envArduino.Command(None, TARGET + '.hex', AVR_BIN_PREFIX + 'size --target=ihex $SOURCE')
353 |
354 | # Reset
355 | def pulseDTR(target, source, env):
356 | import serial
357 | import time
358 | ser = serial.Serial(ARDUINO_PORT)
359 | ser.setDTR(1)
360 | time.sleep(0.5)
361 | ser.setDTR(0)
362 | ser.close()
363 |
364 | if RST_TRIGGER:
365 | reset_cmd = '%s %s' % (RST_TRIGGER, ARDUINO_PORT)
366 | else:
367 | reset_cmd = pulseDTR
368 |
369 | # Upload
370 | UPLOAD_PROTOCOL = getBoardConf('upload.protocol')
371 | UPLOAD_SPEED = getBoardConf('upload.speed')
372 |
373 | if UPLOAD_PROTOCOL == 'stk500':
374 | UPLOAD_PROTOCOL = 'stk500v1'
375 |
376 |
377 | avrdudeOpts = ['-V', '-F', '-c %s' % UPLOAD_PROTOCOL, '-b %s' % UPLOAD_SPEED,
378 | '-p %s' % MCU, '-P %s' % ARDUINO_PORT, '-U flash:w:$SOURCES']
379 | if AVRDUDE_CONF:
380 | avrdudeOpts.append('-C %s' % AVRDUDE_CONF)
381 |
382 | fuse_cmd = '%s %s' % (path.join(path.dirname(AVR_BIN_PREFIX), 'avrdude'),
383 | ' '.join(avrdudeOpts))
384 |
385 | upload = envArduino.Alias('upload', TARGET + '.hex', [reset_cmd, fuse_cmd])
386 | AlwaysBuild(upload)
387 |
388 | # Clean build directory
389 | envArduino.Clean('all', 'build/')
390 |
391 | # vim: et sw=4 fenc=utf-8:
392 |
--------------------------------------------------------------------------------
/SerialPacket/examples/ReceivePackets/ReceivePackets.ino:
--------------------------------------------------------------------------------
1 | // ReceivePackets.ino - Demo application to receive data and command messages
2 | // Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
3 | //
4 | // Program flow:
5 | // -
6 | // Options:
7 | // -
8 |
9 | #include "SerialPacket.h"
10 | #include "defines.h"
11 |
12 | SerialPacket Packet;
13 |
14 | void setup()
15 | {
16 | Packet.begin(115200,0); //begin(speed,nodeID);
17 | }
18 |
19 | void loop()
20 | {
21 | delay(500);
22 | // Packet.sendData(1,uint8_t(6));
23 | }
24 |
25 | /*
26 | SerialEvent occurs whenever a new data comes in the
27 | hardware serial RX. This routine is run between each
28 | time loop() runs, so using delay inside loop can delay
29 | response. Multiple bytes of data may be available.
30 | */
31 |
32 | void serialEvent()
33 | {
34 | Packet.readSerialData();
35 | }
36 |
--------------------------------------------------------------------------------
/SerialPacket/examples/SendAnalogInput/SendAnalogInput.ino:
--------------------------------------------------------------------------------
1 | #include "SerialPacket.h"
2 | #include "defines.h"
3 |
4 | SerialPacket Packet;
5 |
6 | #define SENSORID 2
7 | int a=32760 ;
8 | uint8_t b=0;
9 |
10 | void setup()
11 | {
12 | Packet.begin(115200,1); //begin(speed,nodeID);
13 | }
14 |
15 | void loop()
16 | {
17 |
18 | /*Serial.println(a);
19 | Serial.println(a,HEX);
20 | Packet.sendData(SENSORID, a);
21 |
22 | Serial.println(b);
23 | Serial.println(b,HEX);
24 | Packet.sendData(SENSORID, b)*/
25 | ;
26 |
27 | Packet.sendDataArrayRequest(10,20);
28 | delay(1000); // wait for 100 milliseconds
29 | a++;
30 | b++;
31 | }
32 |
--------------------------------------------------------------------------------
/SerialPacket/examples/SendPackets/SConstruct:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | # scons script for the Arduino sketch
4 | # http://github.com/suapapa/arscons
5 | #
6 | # Copyright (C) 2010-2012 by Homin Lee
7 | #
8 | # This program is free software; you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation; either version 3 of the License, or
11 | # (at your option) any later version.
12 |
13 | # You'll need the serial module: http://pypi.python.org/pypi/pyserial
14 |
15 | # Basic Usage:
16 | # 1. make a folder which have same name of the sketch (ex. Blink/ for Blink.pde)
17 | # 2. put the sketch and SConstruct(this file) under the folder.
18 | # 3. to make the HEX. do following in the folder.
19 | # $ scons
20 | # 4. to upload the binary, do following in the folder.
21 | # $ scons upload
22 |
23 | # Thanks to:
24 | # * Ovidiu Predescu and Lee Pike
25 | # for Mac port and bugfix.
26 | #
27 | # This script tries to determine the port to which you have an Arduino
28 | # attached. If multiple USB serial devices are attached to your
29 | # computer, you'll need to explicitly specify the port to use, like
30 | # this:
31 | #
32 | # $ scons ARDUINO_PORT=/dev/ttyUSB0
33 | #
34 | # To add your own directory containing user libraries, pass EXTRA_LIB
35 | # to scons, like this:
36 | #
37 | # $ scons EXTRA_LIB=
38 | #
39 |
40 | from glob import glob
41 | from itertools import ifilter, imap
42 | from subprocess import check_call, CalledProcessError
43 | import sys
44 | import re
45 | import os
46 | from os import path
47 | from pprint import pprint
48 |
49 | env = Environment()
50 | platform = env['PLATFORM']
51 |
52 | VARTAB = {}
53 |
54 | def resolve_var(varname, default_value):
55 | global VARTAB
56 | # precedence: scons argument -> environment variable -> default value
57 | ret = ARGUMENTS.get(varname, None)
58 | VARTAB[varname] = ('arg', ret)
59 | if ret == None:
60 | ret = os.environ.get(varname, None)
61 | VARTAB[varname] = ('env', ret)
62 | if ret == None:
63 | ret = default_value
64 | VARTAB[varname] = ('dfl', ret)
65 | return ret
66 |
67 | def getUsbTty(rx):
68 | usb_ttys = glob(rx)
69 | return usb_ttys[0] if len(usb_ttys) == 1 else None
70 |
71 | AVR_BIN_PREFIX = None
72 | AVRDUDE_CONF = None
73 |
74 | if platform == 'darwin':
75 | # For MacOS X, pick up the AVR tools from within Arduino.app
76 | ARDUINO_HOME = resolve_var('ARDUINO_HOME',
77 | '/Applications/Arduino.app/Contents/Resources/Java')
78 | ARDUINO_PORT = resolve_var('ARDUINO_PORT', getUsbTty('/dev/tty.usbserial*'))
79 | SKETCHBOOK_HOME = resolve_var('SKETCHBOOK_HOME', '')
80 | AVR_HOME = resolve_var('AVR_HOME',
81 | path.join(ARDUINO_HOME, 'hardware/tools/avr/bin'))
82 | elif platform == 'win32':
83 | # For Windows, use environment variables.
84 | ARDUINO_HOME = resolve_var('ARDUINO_HOME', None)
85 | ARDUINO_PORT = resolve_var('ARDUINO_PORT', '')
86 | SKETCHBOOK_HOME = resolve_var('SKETCHBOOK_HOME', '')
87 | AVR_HOME = resolve_var('AVR_HOME',
88 | path.join(ARDUINO_HOME, 'hardware/tools/avr/bin'))
89 | else:
90 | # For Ubuntu Linux (9.10 or higher)
91 | ARDUINO_HOME = resolve_var('ARDUINO_HOME', '/usr/share/arduino/')
92 | ARDUINO_PORT = resolve_var('ARDUINO_PORT', getUsbTty('/dev/ttyUSB*'))
93 | SKETCHBOOK_HOME = resolve_var('SKETCHBOOK_HOME',
94 | path.expanduser('~/share/arduino/sketchbook/'))
95 | AVR_HOME = resolve_var('AVR_HOME', '')
96 |
97 |
98 | ARDUINO_BOARD = resolve_var('ARDUINO_BOARD', 'atmega328')
99 | ARDUINO_VER = resolve_var('ARDUINO_VER', 0) # Default to 0 if nothing is specified
100 | RST_TRIGGER = resolve_var('RST_TRIGGER', None) # use built-in pulseDTR() by default
101 | EXTRA_LIB = resolve_var('EXTRA_LIB', None) # handy for adding another arduino-lib dir
102 |
103 | pprint(VARTAB, indent = 4)
104 |
105 | if not ARDUINO_HOME:
106 | print 'ARDUINO_HOME must be defined.'
107 | raise KeyError('ARDUINO_HOME')
108 |
109 | ARDUINO_CONF = path.join(ARDUINO_HOME, 'hardware/arduino/boards.txt')
110 | # check given board name, ARDUINO_BOARD is valid one
111 | arduino_boards = path.join(ARDUINO_HOME,'hardware/*/boards.txt')
112 | custom_boards = path.join(SKETCHBOOK_HOME,'hardware/*/boards.txt')
113 | board_files = glob(arduino_boards) + glob(custom_boards)
114 | ptnBoard = re.compile(r'^([^#]*)\.name=(.*)')
115 | boards = {}
116 | for bf in board_files:
117 | for line in open(bf):
118 | result = ptnBoard.match(line)
119 | if result:
120 | boards[result.group(1)] = (result.group(2), bf)
121 |
122 | if ARDUINO_BOARD not in boards:
123 | print "ERROR! the given board name, %s is not in the supported board list:" % ARDUINO_BOARD
124 | print "all available board names are:"
125 | for name, description in boards.iteritems():
126 | print "\t%s for %s" % (name.ljust(14), description[0])
127 | #print "however, you may edit %s to add a new board." % ARDUINO_CONF
128 | sys.exit(-1)
129 |
130 | ARDUINO_CONF = boards[ARDUINO_BOARD][1]
131 |
132 | def getBoardConf(conf, default = None):
133 | for line in open(ARDUINO_CONF):
134 | line = line.strip()
135 | if '=' in line:
136 | key, value = line.split('=')
137 | if key == '.'.join([ARDUINO_BOARD, conf]):
138 | return value
139 | ret = default
140 | if ret == None:
141 | print "ERROR! can't find %s in %s" % (conf, ARDUINO_CONF)
142 | assert(False)
143 | return ret
144 |
145 | ARDUINO_CORE = path.join(ARDUINO_HOME, path.dirname(ARDUINO_CONF),
146 | 'cores/', getBoardConf('build.core', 'arduino'))
147 | ARDUINO_SKEL = path.join(ARDUINO_CORE, 'main.cpp')
148 |
149 | if ARDUINO_VER == 0:
150 | arduinoHeader = path.join(ARDUINO_CORE, 'Arduino.h')
151 | print "No Arduino version specified. Discovered version",
152 | if path.exists(arduinoHeader):
153 | print "100 or above"
154 | ARDUINO_VER = 100
155 | else:
156 | print "0023 or below"
157 | ARDUINO_VER = 23
158 | else:
159 | print "Arduino version " + ARDUINO_VER + " specified"
160 |
161 | # Some OSs need bundle with IDE tool-chain
162 | if platform == 'darwin' or platform == 'win32':
163 | AVRDUDE_CONF = path.join(ARDUINO_HOME, 'hardware/tools/avr/etc/avrdude.conf')
164 |
165 | AVR_BIN_PREFIX = path.join(AVR_HOME, 'avr-')
166 |
167 | ARDUINO_LIBS = [path.join(ARDUINO_HOME, 'libraries')]
168 | if EXTRA_LIB:
169 | ARDUINO_LIBS.append(EXTRA_LIB)
170 | if SKETCHBOOK_HOME:
171 | ARDUINO_LIBS.append(path.join(SKETCHBOOK_HOME, 'libraries'))
172 |
173 |
174 | # Override MCU and F_CPU
175 | MCU = ARGUMENTS.get('MCU', getBoardConf('build.mcu'))
176 | F_CPU = ARGUMENTS.get('F_CPU', getBoardConf('build.f_cpu'))
177 |
178 | # There should be a file with the same name as the folder and
179 | # with the extension .pde or .ino
180 | TARGET = path.basename(path.realpath(os.curdir))
181 | assert(path.exists(TARGET + '.ino') or path.exists(TARGET + '.pde'))
182 | sketchExt = '.ino' if path.exists(TARGET + '.ino') else '.pde'
183 |
184 | cFlags = ['-ffunction-sections', '-fdata-sections', '-fno-exceptions',
185 | '-funsigned-char', '-funsigned-bitfields', '-fpack-struct',
186 | '-fshort-enums', '-Os', '-Wall', '-mmcu=%s' % MCU]
187 | envArduino = Environment(CC = AVR_BIN_PREFIX + 'gcc',
188 | CXX = AVR_BIN_PREFIX + 'g++',
189 | AS = AVR_BIN_PREFIX + 'gcc',
190 | CPPPATH = ['build/core'],
191 | CPPDEFINES = {'F_CPU': F_CPU, 'ARDUINO': ARDUINO_VER},
192 | CFLAGS = cFlags + ['-std=gnu99'],
193 | CCFLAGS = cFlags,
194 | ASFLAGS = ['-assembler-with-cpp','-mmcu=%s' % MCU],
195 | TOOLS = ['gcc','g++', 'as'])
196 |
197 | hwVariant = path.join(ARDUINO_HOME, 'hardware/arduino/variants',
198 | getBoardConf("build.variant", ""))
199 | if hwVariant:
200 | envArduino.Append(CPPPATH = hwVariant)
201 |
202 | def run(cmd):
203 | """Run a command and decipher the return code. Exit by default."""
204 | print ' '.join(cmd)
205 | try:
206 | check_call(cmd)
207 | except CalledProcessError as cpe:
208 | print "Error: return code: " + str(cpe.returncode)
209 | sys.exit(cpe.returncode)
210 |
211 | # WindowXP not supported path.samefile
212 | def sameFile(p1, p2):
213 | if platform == 'win32':
214 | ap1 = path.abspath(p1)
215 | ap2 = path.abspath(p2)
216 | return ap1 == ap2
217 | return path.samefile(p1, p2)
218 |
219 | def fnProcessing(target, source, env):
220 | wp = open(str(target[0]), 'wb')
221 | wp.write(open(ARDUINO_SKEL).read())
222 |
223 | types='''void
224 | int char word long
225 | float double byte long
226 | boolean
227 | uint8_t uint16_t uint32_t
228 | int8_t int16_t int32_t'''
229 | types=' | '.join(types.split())
230 | re_signature = re.compile(r"""^\s* (
231 | (?: (%s) \s+ )?
232 | \w+ \s*
233 | \( \s* ((%s) \s+ \*? \w+ (?:\s*,\s*)? )* \)
234 | ) \s* {? \s* $""" % (types, types), re.MULTILINE | re.VERBOSE)
235 |
236 | prototypes = {}
237 |
238 | for file in glob(path.realpath(os.curdir) + "/*" + sketchExt):
239 | for line in open(file):
240 | result = re_signature.search(line)
241 | if result:
242 | prototypes[result.group(1)] = result.group(2)
243 |
244 | for name in prototypes.iterkeys():
245 | print "%s;" % name
246 | wp.write("%s;\n" % name)
247 |
248 | for file in glob(path.realpath(os.curdir) + "/*" + sketchExt):
249 | print file, TARGET
250 | if not sameFile(file, TARGET + sketchExt):
251 | wp.write('#line 1 "%s"\r\n' % file)
252 | wp.write(open(file).read())
253 |
254 | # Add this preprocessor directive to localize the errors.
255 | sourcePath = str(source[0]).replace('\\', '\\\\')
256 | wp.write('#line 1 "%s"\r\n' % sourcePath)
257 | wp.write(open(str(source[0])).read())
258 |
259 | def fnCompressCore(target, source, env):
260 | core_prefix = 'build/core/'.replace('/', os.path.sep)
261 | core_files = (x for x in imap(str, source)
262 | if x.startswith(core_prefix))
263 | for file in core_files:
264 | run([AVR_BIN_PREFIX + 'ar', 'rcs', str(target[0]), file])
265 |
266 | bldProcessing = Builder(action = fnProcessing) #, suffix = '.cpp', src_suffix = sketchExt)
267 | bldCompressCore = Builder(action = fnCompressCore)
268 | bldELF = Builder(action = AVR_BIN_PREFIX + 'gcc -mmcu=%s ' % MCU +
269 | '-Os -Wl,--gc-sections -lm -o $TARGET $SOURCES -lc')
270 | bldHEX = Builder(action = AVR_BIN_PREFIX + 'objcopy -O ihex -R .eeprom $SOURCES $TARGET')
271 |
272 | envArduino.Append(BUILDERS = {'Processing' : bldProcessing})
273 | envArduino.Append(BUILDERS = {'CompressCore': bldCompressCore})
274 | envArduino.Append(BUILDERS = {'Elf' : bldELF})
275 | envArduino.Append(BUILDERS = {'Hex' : bldHEX})
276 |
277 | ptnSource = re.compile(r'\.(?:c(?:pp)?|S)$')
278 | def gatherSources(srcpath):
279 | return [path.join(srcpath, f) for f
280 | in os.listdir(srcpath) if ptnSource.search(f)]
281 |
282 | # add arduino core sources
283 | VariantDir('build/core', ARDUINO_CORE)
284 | core_sources = gatherSources(ARDUINO_CORE)
285 | core_sources = [x.replace(ARDUINO_CORE, 'build/core/') for x
286 | in core_sources if path.basename(x) != 'main.cpp']
287 |
288 | # add libraries
289 | libCandidates = []
290 | ptnLib = re.compile(r'^[ ]*#[ ]*include [<"](.*)\.h[>"]')
291 | for line in open(TARGET + sketchExt):
292 | result = ptnLib.search(line)
293 | if not result:
294 | continue
295 | # Look for the library directory that contains the header.
296 | filename = result.group(1) + '.h'
297 | for libdir in ARDUINO_LIBS:
298 | for root, dirs, files in os.walk(libdir, followlinks=True):
299 | if filename in files:
300 | libCandidates.append(path.basename(root))
301 |
302 | # Hack. In version 20 of the Arduino IDE, the Ethernet library depends
303 | # implicitly on the SPI library.
304 | if ARDUINO_VER >= 20 and 'Ethernet' in libCandidates:
305 | libCandidates.append('SPI')
306 |
307 | all_libs_sources = []
308 | for index, orig_lib_dir in enumerate(ARDUINO_LIBS):
309 | lib_dir = 'build/lib_%02d' % index
310 | VariantDir(lib_dir, orig_lib_dir)
311 | for libPath in ifilter(path.isdir, glob(path.join(orig_lib_dir, '*'))):
312 | libName = path.basename(libPath)
313 | if not libName in libCandidates:
314 | continue
315 | envArduino.Append(CPPPATH = libPath.replace(orig_lib_dir, lib_dir))
316 | lib_sources = gatherSources(libPath)
317 | utilDir = path.join(libPath, 'utility')
318 | if path.exists(utilDir) and path.isdir(utilDir):
319 | lib_sources += gatherSources(utilDir)
320 | envArduino.Append(CPPPATH = utilDir.replace(orig_lib_dir, lib_dir))
321 | lib_sources = (x.replace(orig_lib_dir, lib_dir) for x in lib_sources)
322 | all_libs_sources.extend(lib_sources)
323 |
324 | # Add raw sources which live in sketch dir.
325 | build_top = path.realpath('.')
326 | VariantDir('build/local/', build_top)
327 | local_sources = gatherSources(build_top)
328 | local_sources = [x.replace(build_top, 'build/local/') for x in local_sources]
329 | if local_sources:
330 | envArduino.Append(CPPPATH = 'build/local')
331 |
332 | # Convert sketch(.pde) to cpp
333 | envArduino.Processing('build/' + TARGET + '.cpp', 'build/' + TARGET + sketchExt)
334 | VariantDir('build', '.')
335 |
336 | sources = ['build/' + TARGET + '.cpp']
337 | #sources += core_sources
338 | sources += local_sources
339 | sources += all_libs_sources
340 |
341 | # Finally Build!!
342 | core_objs = envArduino.Object(core_sources)
343 | objs = envArduino.Object(sources) #, LIBS=libs, LIBPATH='.')
344 | objs = objs + envArduino.CompressCore('build/core.a', core_objs)
345 | envArduino.Elf(TARGET + '.elf', objs)
346 | envArduino.Hex(TARGET + '.hex', TARGET + '.elf')
347 |
348 | # Print Size
349 | # TODO: check binary size
350 | MAX_SIZE = getBoardConf('upload.maximum_size')
351 | print "maximum size for hex file: %s bytes" % MAX_SIZE
352 | envArduino.Command(None, TARGET + '.hex', AVR_BIN_PREFIX + 'size --target=ihex $SOURCE')
353 |
354 | # Reset
355 | def pulseDTR(target, source, env):
356 | import serial
357 | import time
358 | ser = serial.Serial(ARDUINO_PORT)
359 | ser.setDTR(1)
360 | time.sleep(0.5)
361 | ser.setDTR(0)
362 | ser.close()
363 |
364 | if RST_TRIGGER:
365 | reset_cmd = '%s %s' % (RST_TRIGGER, ARDUINO_PORT)
366 | else:
367 | reset_cmd = pulseDTR
368 |
369 | # Upload
370 | UPLOAD_PROTOCOL = getBoardConf('upload.protocol')
371 | UPLOAD_SPEED = getBoardConf('upload.speed')
372 |
373 | if UPLOAD_PROTOCOL == 'stk500':
374 | UPLOAD_PROTOCOL = 'stk500v1'
375 |
376 |
377 | avrdudeOpts = ['-V', '-F', '-c %s' % UPLOAD_PROTOCOL, '-b %s' % UPLOAD_SPEED,
378 | '-p %s' % MCU, '-P %s' % ARDUINO_PORT, '-U flash:w:$SOURCES']
379 | if AVRDUDE_CONF:
380 | avrdudeOpts.append('-C %s' % AVRDUDE_CONF)
381 |
382 | fuse_cmd = '%s %s' % (path.join(path.dirname(AVR_BIN_PREFIX), 'avrdude'),
383 | ' '.join(avrdudeOpts))
384 |
385 | upload = envArduino.Alias('upload', TARGET + '.hex', [reset_cmd, fuse_cmd])
386 | AlwaysBuild(upload)
387 |
388 | # Clean build directory
389 | envArduino.Clean('all', 'build/')
390 |
391 | # vim: et sw=4 fenc=utf-8:
392 |
--------------------------------------------------------------------------------
/SerialPacket/examples/SendPackets/SendPackets.ino:
--------------------------------------------------------------------------------
1 | // SendPackets.ino - Demo application to send packet data
2 | // Copyright 2012 Jeroen Doggen (jeroendoggen@gmail.com)
3 | //
4 | // Program flow:
5 | // - send a data packet every second: x10
6 | // - send a command every second: x5
7 | // - send a 5 field data packet every second: x5
8 | // - send a 10 field data packet every second: x5
9 | // - no packets for 5 seconds
10 | // - restart
11 | // Options:
12 | // - select binary or ASCII mode by changing the #define values in 'includes.h'
13 |
14 | #include "SerialPacket.h"
15 | #include "defines.h"
16 |
17 | SerialPacket Packet;
18 |
19 | uint8_t sensorID=0;
20 | uint8_t commandID=0;
21 |
22 | uint8_t payload=0;
23 |
24 | uint8_t counter=0;
25 |
26 | uint8_t dataArray1[5]={0,1,2,3,4};
27 | uint8_t dataArray2[10]={0,1,2,3,4,5,6,7,8,9};
28 |
29 | void setup()
30 | {
31 | Packet.begin(115200,0); //begin(speed,nodeID);
32 | }
33 |
34 | void loop()
35 | {
36 | // if(counter < 1)
37 | // {
38 | // Packet.sendCommand(10, payload);
39 | // payload++;
40 | // }
41 |
42 | // if(counter < 3)
43 | // {
44 | // Packet.sendCommand(payload);
45 | // payload++;
46 | // }
47 |
48 | // if(counter > 4 && counter < 10)
49 | // {
50 | // Packet.sendCommandReply(commandID, payload);
51 | // payload++;
52 | // }
53 | //
54 | // if(counter > 9 && counter < 15)
55 | // {
56 | // Packet.sendDataRequest(sensorID, payload);
57 | // payload++;
58 | // }
59 | //
60 | // if(counter > 14 && counter < 20)
61 | // {
62 | // Packet.sendData(sensorID, payload);
63 | // payload++;
64 | // }
65 | //
66 | if(counter > 20 && counter < 25) {
67 | Packet.sendData(sensorID, payload);
68 | payload++;
69 | }
70 |
71 | // if(counter > 19 && counter < 25){
72 | // Packet.setPacketType(AGGREGATEDDATA); //data packets
73 | // Packet.sendPacket(dataArray1,sizeof(dataArray1));
74 | // for(int i=0;i 24 && counter < 30){
80 | // Packet.setPacketType(AGGREGATEDDATA); //data packets
81 | // Packet.sendPacket(dataArray2,sizeof(dataArray2));
82 | // for(int i=0;i reply= data packet with sensorvalue=1
8 | // -- the number '2' --> reply= data packet with sensorvalue=2
9 | // -- the letter 'a' --> reply= command packet with commandValue=1
10 | // -- the letter 'b' --> reply= command packet with commandValue=2
11 |
12 | #include "SerialPacket.h"
13 | #include "defines.h"
14 |
15 | SerialPacket Packet;
16 |
17 | uint8_t sensorValue=1;
18 | uint8_t commandValue=1;
19 |
20 | #define MYCOMMAND1 1
21 | #define MYCOMMAND2 1
22 |
23 | #define MYDATA1 1
24 | #define MYDATA2 1
25 |
26 | void setup()
27 | {
28 | Packet.begin(115200,0); //begin(speed,nodeID);
29 | }
30 |
31 | void loop()
32 | {
33 | if (Serial.available() > 0) {
34 | char inByte = Serial.read();
35 |
36 | if (inByte == '1') {
37 | Packet.sendData(sensorValue);
38 | }
39 |
40 | if (inByte == '2') {
41 | Packet.sendData(sensorValue*2);
42 | }
43 |
44 | if (inByte == 'a') {
45 | Packet.sendCommand(commandValue);
46 | }
47 |
48 | if (inByte == 'b') {
49 | Packet.sendCommand(commandValue*2);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/SerialPacket/examples/nose_test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # nose_test.py is copyright 2013 Jeroen Doggen.
4 |
5 | import os
6 | import subprocess
7 | import shutil
8 |
9 |
10 | def test_build_examples():
11 | failures = 0
12 | path = os.getcwd()
13 | for example in os.listdir(path):
14 | if(os.path.isdir(example)):
15 | os.chdir(example)
16 | state = subprocess.call("scons")
17 | if (state != 0):
18 | failures += 1
19 | cleanup(example)
20 | os.chdir("../")
21 | assert (failures == 0)
22 |
23 |
24 | #def test_upload_examples():
25 | #failures = 0
26 | #path = os.getcwd()
27 | #for example in os.listdir(path):
28 | #if(os.path.isdir(example)):
29 | #os.chdir(example)
30 | #state = subprocess.call(["scons", "upload"])
31 | #if (state != 0):
32 | #failures += 1
33 | #cleanup(example)
34 | #os.chdir("../")
35 | #assert (failures == 0)
36 |
37 |
38 | def cleanup(example):
39 | if (os.path.exists("build")):
40 | shutil.rmtree("build")
41 |
42 | hexfile = example + ".hex"
43 | if (os.path.exists(hexfile)):
44 | os.remove(hexfile)
45 |
46 | elffile = example + ".elf"
47 | if (os.path.exists(elffile)):
48 | os.remove(elffile)
49 |
--------------------------------------------------------------------------------
/SerialPacket/keywords.txt:
--------------------------------------------------------------------------------
1 | SerialPacket KEYWORD1
2 | begin KEYWORD2
3 | setPacketType KEYWORD2
4 | sendPacket KEYWORD2
5 |
--------------------------------------------------------------------------------
/SerialPacket/resources/COPYING.LESSER:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | //fsf.org/>
5 | Copyright (C) 2007 Free Software Foundation, Inc.