/// <summary>
        /// Writes the given data in the bluetooth connection interface.
        /// </summary>
        /// <param name="data">The data to be written in the connection interface.</param>
        /// <param name="offset">The start offset in the data to write.</param>
        /// <param name="length">The number of bytes to write.</param>
        /// <exception cref="XBeeException">If there is any XBee error.</exception>
        /// <seealso cref="WriteData(byte[])"/>
        public void WriteData(byte[] data, int offset, int length)
        {
            lock (txLock)
            {
                Debug.WriteLine("----- WriteData " + HexUtils.ByteArrayToHexString(data));
                bool dataWritten = false;

                // Create a task to write in the TX characteristic.
                Task task = Task.Run(async() =>
                {
                    try
                    {
                        byte[] buffer = new byte[length];
                        Array.Copy(data, offset, buffer, 0, length);

                        byte[] dataToWrite = encrypt ? encryptor.TransformFinalBlock(buffer, 0, buffer.Length) : buffer;

                        // Split the data in chunks with a max length of the current MTU.
                        foreach (byte[] chunk in GetChunks(dataToWrite))
                        {
                            // Write the chunk in the TX characteristic.
                            dataWritten = await txCharacteristic.WriteAsync(chunk);
                        }
                    }
                    finally
                    {
                        lock (writeLock)
                        {
                            Monitor.Pulse(writeLock);
                        }
                    }
                });

                if (!task.IsCompleted)
                {
                    // Wait until the task finishes.
                    lock (writeLock)
                    {
                        Monitor.Wait(writeLock, WRITE_TIMEOUT);
                    }
                }

                // If the data could not be written, decrement the counter and throw an exception.
                if (!dataWritten)
                {
                    encryptor.DecrementCounter();
                    throw new XBeeException(ERROR_WRITE);
                }

                // If the task finished with excepction, throw it.
                if (task.Exception != null)
                {
                    throw task.Exception.InnerException;
                }
            }
        }
        /// <summary>
        /// Method executed when new data is received in the RX characteristic.
        /// </summary>
        /// <param name="sender">Characteristic Updated Event sender.</param>
        /// <param name="args">Characteristic Updated Event arguments.</param>
        /// <seealso cref="CharacteristicUpdatedEventArgs"/>
        private void DataReceived(object sender, CharacteristicUpdatedEventArgs args)
        {
            byte[] value = args.Characteristic.Value;

            // If the communication is encrypted, decrypt the received data.
            if (encrypt)
            {
                value = decryptor.TransformFinalBlock(value, 0, value.Length);
            }

            Debug.WriteLine("----- RX char " + HexUtils.ByteArrayToHexString(value));

            Stream.Write(value, 0, value.Length);

            // Notify that data has been received.
            lock (this)
            {
                Monitor.Pulse(this);
            }
        }
        /// <summary>
        /// Starts the read or write operation.
        /// </summary>
        /// <param name="read"><c>true</c> to start the read operation, <c>false</c> to start the
        /// write operation.</param>
        private void StartOperation(bool read)
        {
            // Show a progress dialog while performing the operation.
            ShowLoadingDialog(read ? "Reading settings..." : "Writing settings...");

            // The read/write process blocks the UI interface, so it must be done in a different thread.
            Task.Run(() =>
            {
                try
                {
                    if (read)
                    {
                        // Read the values.
                        ShValue = HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("SH"));
                        SlValue = HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("SL"));
                        BlValue = HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("BL"));
                        NiValue = Encoding.Default.GetString(BleDevice.XBeeDevice.GetParameter("NI"));
                        ApValue = int.Parse(HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("AP")));
                        D9Value = int.Parse(HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("D9")));
                        VrValue = HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("VR"));
                        HvValue = HexUtils.ByteArrayToHexString(BleDevice.XBeeDevice.GetParameter("HV"));
                    }
                    else
                    {
                        // Write the values.
                        BleDevice.XBeeDevice.SetParameter("NI", Encoding.Default.GetBytes(NiValue));
                        BleDevice.XBeeDevice.SetParameter("AP", HexUtils.HexStringToByteArray(ApValue.ToString()));
                        BleDevice.XBeeDevice.SetParameter("D9", HexUtils.HexStringToByteArray(D9Value.ToString()));
                    }
                }
                catch (XBeeException e)
                {
                    ShowErrorDialog("Error performing operation", e.Message);
                }
                // Close the dialog.
                HideLoadingDialog();
            });
        }
Beispiel #4
0
        /// <summary>
        /// Generates the Device ID corresponding to this <see cref="XBee64BitAddress"/> to be used in Device Cloud.
        /// </summary>
        /// <returns>Device ID corresponding to this address.</returns>
        public string GenerateDeviceID()
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    sb.Append(HexUtils.ByteArrayToHexString(new byte[] { 0 }));
                }
                sb.Append(DEVICE_ID_SEPARATOR);
            }
            // Here we should have "00000000-00000000-"
            // Append first three bytes of the MAC Address, discard first 2.
            sb.Append(HexUtils.ByteArrayToHexString(new byte[] { address[2], address[3], address[4] }));
            sb.Append(DEVICE_ID_MAC_SEPARATOR);
            sb.Append(DEVICE_ID_SEPARATOR);
            sb.Append(DEVICE_ID_MAC_SEPARATOR);
            // Here we should have "00000000-00000000-XXXXXXFF-FF"
            // Append second three bytes of the MAC Address.
            sb.Append(HexUtils.ByteArrayToHexString(new byte[] { address[5], address[6], address[7] }));
            return(sb.ToString());
        }
Beispiel #5
0
 /// <summary>
 /// Returns the <see cref="SrpError"/> in string format.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The <see cref="SrpError"/> in string format.</returns>
 public static string ToDisplayString(this SrpError source)
 {
     return(string.Format("({0}) {1}", HexUtils.ByteArrayToHexString(ByteUtils.IntToByteArray((byte)source)), GetName(source)));
 }
        /**
         * Parses the given node discovery API data to create and return a remote
         * XBee Device.
         *
         * @param data Byte array with the data to parse.
         * @param localDevice The local device that received the remote XBee data.
         *
         * @return Discovered XBee device.
         */
        private async Task <RemoteXBeeDevice> ParseDiscoveryAPIData(byte[] data, XBeeDevice localDevice)
        {
            if (data == null)
            {
                return(null);
            }

            RemoteXBeeDevice device = null;
            XBee16BitAddress addr16 = null;
            XBee64BitAddress addr64 = null;
            String           id     = null;
            // TODO role of the device: coordinator, router, end device or unknown.
            //XBeeDeviceType role = XBeeDeviceType.UNKNOWN;
            int signalStrength = 0;

            byte[] profileID      = null;
            byte[] manufacturerID = null;

            using (var inputStream = new MemoryStream(data))
            {
                // Read 16 bit address.
                addr16 = new XBee16BitAddress(await ByteUtils.ReadBytes(2, inputStream));
                // Read 64 bit address.
                addr64 = new XBee64BitAddress(await ByteUtils.ReadBytes(8, inputStream));


                switch (localDevice.XBeeProtocol)
                {
                case XBeeProtocol.ZIGBEE:
                case XBeeProtocol.DIGI_MESH:
                case XBeeProtocol.ZNET:
                case XBeeProtocol.DIGI_POINT:
                case XBeeProtocol.XLR:
                // TODO [XLR_DM] The next version of the XLR will add DigiMesh support.
                // For the moment only point-to-multipoint is supported in this kind of devices.
                case XBeeProtocol.XLR_DM:
                    // Read node identifier.
                    id = ByteUtils.ReadString(inputStream);
                    // Read parent address.
                    XBee16BitAddress parentAddress = new XBee16BitAddress(await ByteUtils.ReadBytes(2, inputStream));
                    // TODO Read device type.
                    //role = XBeeDeviceType.get(inputStream.read());
                    // Consume status byte, it is not used yet.
                    await ByteUtils.ReadBytes(1, inputStream);

                    // Read profile ID.
                    profileID = await ByteUtils.ReadBytes(2, inputStream);

                    // Read manufacturer ID.
                    manufacturerID = await ByteUtils.ReadBytes(2, inputStream);

                    logger.DebugFormat("{0}Discovered {1} device: 16-bit[{2}], 64-bit[{3}], id[{4}], parent[{5}], profile[{6}], manufacturer[{7}].",
                                       xbeeDevice.ToString(), localDevice.XBeeProtocol.GetDescription(), addr16,
                                       addr64, id, parentAddress, HexUtils.ByteArrayToHexString(profileID),
                                       HexUtils.ByteArrayToHexString(manufacturerID));

                    break;

                case XBeeProtocol.RAW_802_15_4:
                    // Read strength signal byte.
                    signalStrength = inputStream.ReadByte();
                    // Read node identifier.
                    id = ByteUtils.ReadString(inputStream);

                    logger.DebugFormat("{0}Discovered {1} device: 16-bit[{2}], 64-bit[{3}], id[{4}], rssi[{5}].",
                                       xbeeDevice.ToString(), localDevice.XBeeProtocol.GetDescription(), addr16, addr64, id, signalStrength);

                    break;

                case XBeeProtocol.UNKNOWN:
                default:
                    logger.DebugFormat("{0}Discovered {1} device: 16-bit[{2}], 64-bit[{3}].",
                                       xbeeDevice.ToString(), localDevice.XBeeProtocol.GetDescription(), addr16, addr64);
                    break;
                }

                // Create device and fill with parameters.
                switch (localDevice.XBeeProtocol)
                {
                case XBeeProtocol.ZIGBEE:
                    device = new RemoteZigBeeDevice(localDevice, addr64, addr16, id /*, role*/);
                    // TODO profileID and manufacturerID
                    break;

                case XBeeProtocol.DIGI_MESH:
                    device = new RemoteDigiMeshDevice(localDevice, addr64, id /*, role*/);
                    // TODO profileID and manufacturerID
                    break;

                case XBeeProtocol.DIGI_POINT:
                    device = new RemoteDigiPointDevice(localDevice, addr64, id /*, role*/);
                    // TODO profileID and manufacturerID
                    break;

                case XBeeProtocol.RAW_802_15_4:
                    device = new RemoteRaw802Device(localDevice, addr64, addr16, id /*, role*/);
                    // TODO signalStrength
                    break;

                default:
                    device = new RemoteXBeeDevice(localDevice, addr64, addr16, id /*, role*/);
                    break;
                }
            }

            return(device);
        }
Beispiel #7
0
        /// <summary>
        /// Provisions the device with the data entered.
        /// </summary>
        public void ProvisionDevice()
        {
            Task.Run(async() =>
            {
                ShowLoadingDialog("Provisioning device...");

                string devName = DeviceId;
                // If the device is an irrigation station, format its device ID.
                if (!isController)
                {
                    devName = string.Format(STATION_IDENTIFIER, DeviceId);
                }

                // Generate the provisioning JSON and send it to the device.
                JObject json = JObject.Parse(@"{"
                                             + "'" + JsonConstants.ITEM_OP + "': '" + JsonConstants.OP_WRITE + "',"
                                             + "'" + JsonConstants.ITEM_PROP + "': {"
                                             + "'" + JsonConstants.PROP_NAME + "': '" + devName + "',"
                                             + (isController && isMainController ? "'" + JsonConstants.PROP_MAIN_CONTROLLER + "': 'true'," : "")
                                             + "'" + JsonConstants.PROP_LATITUDE + "': '" + FormatLocation(Location.Latitude) + "',"
                                             + "'" + JsonConstants.PROP_LONGITUDE + "': '" + FormatLocation(Location.Longitude) + "',"
                                             + (Location.Altitude.HasValue ? "'" + JsonConstants.PROP_ALTITUDE + "': '" + FormatLocation(Math.Round(Location.Altitude.Value)) + "'," : "")
                                             + "'" + JsonConstants.PROP_PAN_ID + "': '" + NetworkId + "',"
                                             + (!string.IsNullOrEmpty(NetworkPassword) ? "'" + JsonConstants.PROP_PASS + "': '" + NetworkPassword + "'" : "")
                                             + "}"
                                             + "}");

                string response = SendData(json, JsonConstants.OP_WRITE, true);
                if (response == null || !response.Equals(""))
                {
                    await ShowProvisioningError("Could not provision the device" + (response != null ? ": " + response : "") + ".");
                    return;
                }

                // If the device is a controller, store the newtork ID and register it in Digi Remote Manager.
                if (isController)
                {
                    AppPreferences.AddNetworkId(NetworkId);
                    try
                    {
                        RegisterDeviceDRM();
                    }
                    catch (Exception e)
                    {
                        await ShowProvisioningError(string.Format("Could not register the device in Digi Remote Manager: {0}", e.Message));
                        return;
                    }
                }
                // If the device is a station, wait until it is joined to the network.
                else
                {
                    HideLoadingDialog();
                    ShowLoadingDialog("Waiting for device to join the network...");

                    long deadline = Environment.TickCount + ASSOCIATION_TIMEOUT;
                    int ai        = -1;
                    // Wait until the device is associated or the timeout elapses.
                    while (Environment.TickCount < deadline && ai != 0)
                    {
                        ai = int.Parse(HexUtils.ByteArrayToHexString(bleDevice.XBeeDevice.GetParameter(AT_ASSOCIATION)), System.Globalization.NumberStyles.HexNumber);
                        await Task.Delay(1000);
                    }

                    if (ai != 0)
                    {
                        await ShowProvisioningError(string.Format("The device could not associate to the configured network. " +
                                                                  "Please make sure the irrigation controller with network ID '{0}' is powered on.", NetworkId));
                        return;
                    }
                }

                FinishProvisioning();

                HideLoadingDialog();

                await DisplayAlert("Provisioning finished", "The device has been provisioned successfully.");

                // Go to the root page.
                Device.BeginInvokeOnMainThread(async() =>
                {
                    await Application.Current.MainPage.Navigation.PopToRootAsync();
                });
            });
        }
 /// <summary>
 /// Returns the string representation of this packet.
 /// </summary>
 /// <returns>The string representation of this packet.</returns>
 public override string ToString()
 {
     return(HexUtils.ByteArrayToHexString(GenerateByteArray()));
 }
Beispiel #9
0
 public override string ToString()
 {
     return(HexUtils.ByteArrayToHexString(address));
 }