diff --git a/NetduinoToEventHub/NetduinoToEventHub.csproj b/NetduinoToEventHub/NetduinoToEventHub.csproj new file mode 100644 index 0000000..267bfc5 --- /dev/null +++ b/NetduinoToEventHub/NetduinoToEventHub.csproj @@ -0,0 +1,57 @@ + + + + NetduinoToEventHub + Exe + NetduinoToEventHub + {b69e3092-b931-443c-abe7-7e7b65f2a37f};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 9.0.21022 + 2.0 + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9} + v4.3 + $(MSBuildExtensionsPath32)\Microsoft\.NET Micro Framework\ + Netduino + USB + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + {0BFFA8ED-1C52-4C0C-97A2-6825A6D528CA} + IoTClient.NetMf43 + + + \ No newline at end of file diff --git a/NetduinoToEventHub/NtpClient.cs b/NetduinoToEventHub/NtpClient.cs new file mode 100644 index 0000000..60a3c96 --- /dev/null +++ b/NetduinoToEventHub/NtpClient.cs @@ -0,0 +1,111 @@ +/* + * NtpClient.cs + * + * Copyright (c) 2009, Michael Schwarz (http://www.schwarz-interactive.de) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * MS 09-02-16 added NtpClient + * + * + */ +using System; +using System.Text; +using System.Net; +using System.Net.Sockets; + +namespace MFToolkit.Net.Ntp +{ + /// + /// Static class to receive the time from a NTP server. + /// + public class NtpClient + { + /// + /// Gets the current DateTime from time-a.nist.gov. + /// + /// A DateTime containing the current time. + public static DateTime GetNetworkTime() + { + return GetNetworkTime("time-a.nist.gov"); + } + + /// + /// Gets the current DateTime from . + /// + /// The hostname of the NTP server. + /// A DateTime containing the current time. + public static DateTime GetNetworkTime(string ntpServer) + { + IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList; + + if (address == null || address.Length == 0) + throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", "ntpServer"); + + IPEndPoint ep = new IPEndPoint(address[0], 123); + + return GetNetworkTime(ep); + } + + /// + /// Gets the current DateTime form IPEndPoint. + /// + /// The IPEndPoint to connect to. + /// A DateTime containing the current time. + public static DateTime GetNetworkTime(IPEndPoint ep) + { + Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + s.Connect(ep); + + byte[] ntpData = new byte[48]; // RFC 2030 + ntpData[0] = 0x1B; + for (int i = 1; i < 48; i++) + ntpData[i] = 0; + + s.Send(ntpData); + s.Receive(ntpData); + + byte offsetTransmitTime = 40; + ulong intpart = 0; + ulong fractpart = 0; + + for (int i = 0; i <= 3; i++) + intpart = 256 * intpart + ntpData[offsetTransmitTime + i]; + + for (int i = 4; i <= 7; i++) + fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i]; + + ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L); + s.Close(); + + TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond); + + DateTime dateTime = new DateTime(1900, 1, 1); + dateTime += timeSpan; + + TimeSpan offsetAmount = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime); + DateTime networkDateTime = (dateTime + offsetAmount); + + return networkDateTime; + } + } +} + diff --git a/NetduinoToEventHub/Program.cs b/NetduinoToEventHub/Program.cs new file mode 100644 index 0000000..9fcb97d --- /dev/null +++ b/NetduinoToEventHub/Program.cs @@ -0,0 +1,149 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using Microsoft.SPOT; +using Microsoft.SPOT.Hardware; +using SecretLabs.NETMF.Hardware; +using SecretLabs.NETMF.Hardware.Netduino; +using ppatierno.TI; +using ppatierno.ST; +using ppatierno.IoT; +using Microsoft.SPOT.Time; +using System.Collections; + +namespace NetduinoToEventHub +{ + public class Program + { + // TI Sensor Tag parameters + private byte[] TI_SENSORTAG_ADDR = { 0x4E, 0x58, 0x6E, 0xE5, 0xC5, 0x78 }; +#if HEART_RATE + private byte[] BlueNRG_HRM_ADDR = { 0xFD, 0x00, 0x25, 0xEC, 0x02, 0x04 }; + + BlueNRG_HRM blueNGR_HRM; +#endif + TISensorTag tiSensorTag; + IIoTClient iotClient; + +#if CONNECT_THE_DOTS + // Event Hub connection string + private string connectionString = "[EVENT_HUB_CONNECTION_STRING]"; + private string eventhubentity = "[EVENT_HUB_NAME]"; +#else + // Event Hub connection string + private string connectionString = "[EVENT_HUB_CONNECTION_STRING]"; + private string eventhubentity = "[EVENT_HUB_NAME]"; +#endif + + static AutoResetEvent networkAvailableEvent = new AutoResetEvent(false); + static AutoResetEvent networkAddressChangedEvent = new AutoResetEvent(false); + + public static void Main() + { + (new Program()).Run(); + } + + public void Run() + { + Microsoft.SPOT.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged; + Microsoft.SPOT.Net.NetworkInformation.NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; + + networkAvailableEvent.WaitOne(); + Debug.Print("link is up!"); + networkAddressChangedEvent.WaitOne(); + Debug.Print("address acquired: " + Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].IPAddress); + + Debug.Print("\r\n*** GET NETWORK INTERFACE SETTINGS ***"); + Microsoft.SPOT.Net.NetworkInformation.NetworkInterface[] networkInterfaces = Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); + Debug.Print("Found " + networkInterfaces.Length + " network interfaces."); + + // get date/time via NTP + DateTime dateTime = MFToolkit.Net.Ntp.NtpClient.GetNetworkTime(); + Utility.SetLocalTime(dateTime); + + // set and open the IoT client + if (this.iotClient == null) + { +#if CONNECT_THE_DOTS + this.iotClient = new IoTClientDots("netduino", Guid.NewGuid().ToString(), connectionString, eventhubentity); +#elif HEART_RATE + this.iotClient = new IoTClientHealth("netduino", Guid.NewGuid().ToString(), connectionString, eventhubentity); +#else + this.iotClient = new IoTClient("netduino", Guid.NewGuid().ToString(), connectionString, eventhubentity); +#endif + } + + if (!this.iotClient.IsOpen) + this.iotClient.Open(); + + // NOTE : seems to be a .Net MF bug when in this ethernet handler and you are waiting + // a response on serial port, the data can't be received. + // Launch serial communication with BLE module on different thread. + Thread t = new Thread(this.SensorsSetup); + t.Start(); + //this.SensorsSetup(); + + Thread.Sleep(Timeout.Infinite); + } + + void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) + { + Debug.Print("NetworkAddressChanged"); + networkAddressChangedEvent.Set(); + } + + void NetworkChange_NetworkAvailabilityChanged(object sender, Microsoft.SPOT.Net.NetworkInformation.NetworkAvailabilityEventArgs e) + { + Debug.Print("NetworkAvailabilityChanged " + e.IsAvailable); + if (e.IsAvailable) + { + networkAvailableEvent.Set(); + } + } + + private void SensorsSetup() + { +#if HEART_RATE + BlueNRG_HRMSettings settings = + new BlueNRG_HRMSettings + { + Address = BlueNRG_HRM_ADDR + }; + + this.blueNGR_HRM = new BlueNRG_HRM(settings); + + this.blueNGR_HRM.SensorValueChanged += device_SensorValueChanged; + + this.blueNGR_HRM.Open(); +#else + // setup TI Sensor Tag + TISensorTagSettings settings = + new TISensorTagSettings + { + Address = TI_SENSORTAG_ADDR, + IsTemperatureEnabled = true, + IsHumidityEnabled = true, + IsAccelerometerEnabled = true, + Period = 100 + }; + + this.tiSensorTag = new TISensorTag(settings); + + // set notification handlers + this.tiSensorTag.SensorValueChanged += device_SensorValueChanged; + + // open connection and start reading from sensors + this.tiSensorTag.Open(); +#endif + } + + void device_SensorValueChanged(object sender, IDictionary e) + { + if ((this.iotClient != null) && (this.iotClient.IsOpen)) + { + this.iotClient.SendAsync(e); + } + } + } +} diff --git a/NetduinoToEventHub/Properties/AssemblyInfo.cs b/NetduinoToEventHub/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..15c408a --- /dev/null +++ b/NetduinoToEventHub/Properties/AssemblyInfo.cs @@ -0,0 +1,25 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NetduinoToEventHub")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NetduinoToEventHub")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ble2azure.sln b/ble2azure.sln index 74590bf..9031908 100644 --- a/ble2azure.sln +++ b/ble2azure.sln @@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FEZSpiderMonitor", "FEZSpid EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FEZSpiderToEventHub", "FEZSpiderToEventHub\FEZSpiderToEventHub.csproj", "{FA37C00B-BF32-4DE4-9873-928536D40759}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetduinoToEventHub", "NetduinoToEventHub\NetduinoToEventHub.csproj", "{5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -71,6 +73,12 @@ Global {FA37C00B-BF32-4DE4-9873-928536D40759}.Release|Any CPU.ActiveCfg = Release|Any CPU {FA37C00B-BF32-4DE4-9873-928536D40759}.Release|Any CPU.Build.0 = Release|Any CPU {FA37C00B-BF32-4DE4-9873-928536D40759}.Release|Any CPU.Deploy.0 = Release|Any CPU + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}.Release|Any CPU.Build.0 = Release|Any CPU + {5AEF163A-1DD4-43BD-B52C-F84A7340D9A9}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/images/overall_2.png b/images/overall_2.png new file mode 100644 index 0000000..6c0a840 Binary files /dev/null and b/images/overall_2.png differ