/// <summary> /// Writes an array of FLOAT32, INT32, DOUBLE64 or ASCII (char) values to the device. /// The data length is given by the value parameter. /// This method does only return when all data is downloaded. /// The data is being written in an loop with several sub queries. /// During this command is working, it is possible to use other commands with an different thread. /// </summary> /// <param name="address">Device Address. Use null to use the DefaultDeviceAddress defined on MeComQuerySet.</param> /// <param name="parameterId">Device Parameter ID.</param> /// <param name="instance">Parameter Instance. (usually 1)</param> /// <param name="type">Specifies the type of the value to be written.</param> /// <param name="values">Data to be written (can be float[], int[], double[] or string.</param> /// <param name="callback">Is called every time when the progress has changed.</param> /// <exception cref="ComCommandException">when the command fails. Check the inner exception for details.</exception> public void SetBigData(byte?address, UInt16 parameterId, byte instance, MeParType type, dynamic values, ProgressUpdateCallback callback) { int maxDataSize = meQuerySet.MaxTxPayloadSize - 22; //-xx Bytes used for commands int nrOfElementsPerPackage = 0; switch (type) { case MeParType.FLOAT32: nrOfElementsPerPackage = maxDataSize / 8; break; case MeParType.INT32: nrOfElementsPerPackage = maxDataSize / 8; break; case MeParType.DOUBLE64: nrOfElementsPerPackage = maxDataSize / 16; break; case MeParType.LATIN1: values += (char)0; //Add zero terminator nrOfElementsPerPackage = maxDataSize / 2; break; case MeParType.BYTE: nrOfElementsPerPackage = maxDataSize / 2; break; default: throw new ArgumentOutOfRangeException("Unknown EParType: " + type); } int nrOfPackages = (values.Length - 1) / nrOfElementsPerPackage + 1; try { int totalSentElements = 0; MemoryStream totalStream = new MemoryStream(); for (int packageNr = 0; packageNr < nrOfPackages; packageNr++) { bool lastPackage = (packageNr + 1) == nrOfPackages; int nrOfElementsInThisPackage = values.Length - totalSentElements; if (nrOfElementsInThisPackage > nrOfElementsPerPackage) { nrOfElementsInThisPackage = nrOfElementsPerPackage; } MeComPacket txFrame = new MeComPacket('#', address); MeComVarConvert.AddString(txFrame.Payload, "VB"); MeComVarConvert.AddUint16(txFrame.Payload, parameterId); MeComVarConvert.AddUint8(txFrame.Payload, instance); MeComVarConvert.AddUint32(txFrame.Payload, (uint)totalSentElements); //write start position MeComVarConvert.AddUint16(txFrame.Payload, (ushort)nrOfElementsInThisPackage); if (lastPackage) { MeComVarConvert.AddUint8(txFrame.Payload, 1); } else { MeComVarConvert.AddUint8(txFrame.Payload, 0); } switch (type) { case MeParType.FLOAT32: for (int i = 0; i < nrOfElementsInThisPackage; i++) { MeComVarConvert.AddFloat32(txFrame.Payload, values[totalSentElements + i]); } break; case MeParType.INT32: for (int i = 0; i < nrOfElementsInThisPackage; i++) { MeComVarConvert.AddUint32(txFrame.Payload, values[totalSentElements + i]); } break; case MeParType.DOUBLE64: for (int i = 0; i < nrOfElementsInThisPackage; i++) { MeComVarConvert.AddDouble64(txFrame.Payload, values[totalSentElements + i]); } break; case MeParType.LATIN1: MeComVarConvert.AddEncodedString(txFrame.Payload, values.Substring(totalSentElements, nrOfElementsInThisPackage)); break; case MeParType.BYTE: for (int i = 0; i < nrOfElementsInThisPackage; i++) { MeComVarConvert.AddUint8(txFrame.Payload, values[totalSentElements + i]); } break; } int timeout = 0; while (timeout < 50) //Manage device busy { timeout++; try { meQuerySet.Set(txFrame); break; } catch (ServerException ex) { if (ex.ServerErrorCode != 2) { throw; } TraceLog.Verbose("Device busy detected. Timeout {0}", timeout); Thread.Sleep(10); } } totalSentElements += nrOfElementsInThisPackage; callback?.Invoke(100.0 / nrOfPackages * (packageNr + 1)); } } catch (Exception Ex) { throw new ComCommandException(String.Format("Set Value failed: Address: {0}; ID: {1}; Inst: {2}; Detail: {3}", address, parameterId, instance, Ex.Message), Ex); } }