In continuation to my previous question C# Confluent.Kafka SetValueDeserializer object deserialization, I have tried creating my custom deserializer to deserialize protobuf message but getting this error:
System.InvalidOperationException: 'Type is not expected, and no contract can be inferred: Ileco.Chimp.Proto.FinalValue'
on line:
return Serializer.Deserialize<T>(stream);
Here my consumer and deserializer:
class Worker
{
public static void Consumer(string brokerList, string connStr, string consumergroup, string topic, string cacertlocation)
{
var config = new ConsumerConfig
{
BootstrapServers = brokerList,
SecurityProtocol = SecurityProtocol.SaslSsl,
SocketTimeoutMs = 60000, //this corresponds to the Consumer config `request.timeout.ms`
SessionTimeoutMs = 30000,
SaslMechanism = SaslMechanism.Plain,
SaslUsername = "$ConnectionString",
SaslPassword = connStr,
SslCaLocation = cacertlocation,
GroupId = consumergroup,
AutoOffsetReset = AutoOffsetReset.Earliest,
BrokerVersionFallback = "1.0.0", //Event Hubs for Kafka Ecosystems supports Kafka v1.0+, a fallback to an older API will fail
//Debug = "security,broker,protocol" //Uncomment for librdkafka debugging information
};
using (var consumer = new ConsumerBuilder<string, FinalValue>(config)
.SetKeyDeserializer(Deserializers.Utf8)
.SetValueDeserializer(new MyCustomDeserializer<FinalValue>())
.SetErrorHandler((_, e) => Console.WriteLine($"Error: {e.Reason}"))
.Build())
{
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => { e.Cancel = true; cts.Cancel(); };
consumer.Subscribe(topic);
Console.WriteLine("Consuming messages from topic: " + topic + ", broker(s): " + brokerList);
while (true)
{
try
{
var msg = consumer.Consume(cts.Token);
Console.WriteLine($"Received: '{msg.Message.Value}'");
//var bytes = Encoding.ASCII.GetBytes(msg.Message.Value);
//var fv = FromByteArray<ProtobufMsg>(bytes);
//var proto = ProtoDeserialize<ProtobufMsg>(bytes);
}
catch (ConsumeException e)
{
Console.WriteLine($"Consume error: {e.Error.Reason}");
}
catch (Exception e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
public class MyCustomDeserializer<T> : IDeserializer<T>
{
public T Deserialize(ReadOnlySpan<byte> data, bool isNull, Confluent.Kafka.SerializationContext context)
{
using (var stream = new MemoryStream(data.ToArray()))
{
return Serializer.Deserialize<T>(stream);
}
}
}
FinalValue.proto
syntax = "proto3";
package ileco.chimp.proto;
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
option java_package = "ileco.chimp.proto";
option java_outer_classname = "FinalValueProtos";
message FinalValue {
google.protobuf.Timestamp timestamp = 1;
uint32 inputId = 2;
google.protobuf.DoubleValue value = 3;
uint32 sourceId = 4;
string inputGuid = 5;
}
FinalValue.cs
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: proto/FinalValue.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Ileco.Chimp.Proto {
/// <summary>Holder for reflection information generated from proto/FinalValue.proto</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class FinalValueReflection {
#region Descriptor
/// <summary>File descriptor for proto/FinalValue.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static FinalValueReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChZwcm90by9GaW5hbFZhbHVlLnByb3RvEhFpbGVjby5jaGltcC5wcm90bxof",
"Z29vZ2xlL3Byb3RvYnVmL3RpbWVzdGFtcC5wcm90bxoeZ29vZ2xlL3Byb3Rv",
"YnVmL3dyYXBwZXJzLnByb3RvIp4BCgpGaW5hbFZhbHVlEi0KCXRpbWVzdGFt",
"cBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDwoHaW5wdXRJ",
"ZBgCIAEoDRIrCgV2YWx1ZRgDIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi",
"bGVWYWx1ZRIQCghzb3VyY2VJZBgEIAEoDRIRCglpbnB1dEd1aWQYBSABKAlC",
"JQoRaWxlY28uY2hpbXAucHJvdG9CEEZpbmFsVmFsdWVQcm90b3NiBnByb3Rv",
"Mw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Ileco.Chimp.Proto.FinalValue), global::Ileco.Chimp.Proto.FinalValue.Parser, new[]{ "Timestamp", "InputId", "Value", "SourceId", "InputGuid" }, null, null, null)
}));
}
#endregion
}
#region Messages
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class FinalValue : pb::IMessage<FinalValue> {
private static readonly pb::MessageParser<FinalValue> _parser = new pb::MessageParser<FinalValue>(() => new FinalValue());
public static pb::MessageParser<FinalValue> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Ileco.Chimp.Proto.FinalValueReflection.Descriptor.MessageTypes[0]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public FinalValue() {
OnConstruction();
}
partial void OnConstruction();
public FinalValue(FinalValue other) : this() {
Timestamp = other.timestamp_ != null ? other.Timestamp.Clone() : null;
inputId_ = other.inputId_;
Value = other.Value;
sourceId_ = other.sourceId_;
inputGuid_ = other.inputGuid_;
}
public FinalValue Clone() {
return new FinalValue(this);
}
/// <summary>Field number for the "timestamp" field.</summary>
public const int TimestampFieldNumber = 1;
private global::Google.Protobuf.WellKnownTypes.Timestamp timestamp_;
public global::Google.Protobuf.WellKnownTypes.Timestamp Timestamp {
get { return timestamp_; }
set {
timestamp_ = value;
}
}
/// <summary>Field number for the "inputId" field.</summary>
public const int InputIdFieldNumber = 2;
private uint inputId_;
public uint InputId {
get { return inputId_; }
set {
inputId_ = value;
}
}
/// <summary>Field number for the "value" field.</summary>
public const int ValueFieldNumber = 3;
private static readonly pb::FieldCodec<double?> _single_value_codec = pb::FieldCodec.ForStructWrapper<double>(26);
private double? value_;
public double? Value {
get { return value_; }
set {
value_ = value;
}
}
/// <summary>Field number for the "sourceId" field.</summary>
public const int SourceIdFieldNumber = 4;
private uint sourceId_;
public uint SourceId {
get { return sourceId_; }
set {
sourceId_ = value;
}
}
/// <summary>Field number for the "inputGuid" field.</summary>
public const int InputGuidFieldNumber = 5;
private string inputGuid_ = "";
public string InputGuid {
get { return inputGuid_; }
set {
inputGuid_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
public override bool Equals(object other) {
return Equals(other as FinalValue);
}
public bool Equals(FinalValue other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!object.Equals(Timestamp, other.Timestamp)) return false;
if (InputId != other.InputId) return false;
if (Value != other.Value) return false;
if (SourceId != other.SourceId) return false;
if (InputGuid != other.InputGuid) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (timestamp_ != null) hash ^= Timestamp.GetHashCode();
if (InputId != 0) hash ^= InputId.GetHashCode();
if (value_ != null) hash ^= Value.GetHashCode();
if (SourceId != 0) hash ^= SourceId.GetHashCode();
if (InputGuid.Length != 0) hash ^= InputGuid.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (timestamp_ != null) {
output.WriteRawTag(10);
output.WriteMessage(Timestamp);
}
if (InputId != 0) {
output.WriteRawTag(16);
output.WriteUInt32(InputId);
}
if (value_ != null) {
_single_value_codec.WriteTagAndValue(output, Value);
}
if (SourceId != 0) {
output.WriteRawTag(32);
output.WriteUInt32(SourceId);
}
if (InputGuid.Length != 0) {
output.WriteRawTag(42);
output.WriteString(InputGuid);
}
}
public int CalculateSize() {
int size = 0;
if (timestamp_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Timestamp);
}
if (InputId != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(InputId);
}
if (value_ != null) {
size += _single_value_codec.CalculateSizeWithTag(Value);
}
if (SourceId != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(SourceId);
}
if (InputGuid.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(InputGuid);
}
return size;
}
public void MergeFrom(FinalValue other) {
if (other == null) {
return;
}
if (other.timestamp_ != null) {
if (timestamp_ == null) {
timestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
Timestamp.MergeFrom(other.Timestamp);
}
if (other.InputId != 0) {
InputId = other.InputId;
}
if (other.value_ != null) {
if (value_ == null || other.Value != 0D) {
Value = other.Value;
}
}
if (other.SourceId != 0) {
SourceId = other.SourceId;
}
if (other.InputGuid.Length != 0) {
InputGuid = other.InputGuid;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10: {
if (timestamp_ == null) {
timestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
input.ReadMessage(timestamp_);
break;
}
case 16: {
InputId = input.ReadUInt32();
break;
}
case 26: {
double? value = _single_value_codec.Read(input);
if (value_ == null || value != 0D) {
Value = value;
}
break;
}
case 32: {
SourceId = input.ReadUInt32();
break;
}
case 42: {
InputGuid = input.ReadString();
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code
As I noted yesterday, you appear to have used the Google .proto processing tools (protoc), but are using protobuf-net; if you want to use protobuf-net, similar command-line/IDE/build/etc tools exist that are compatible with the protobuf-net library, or you can use https://protogen.marcgravell.com/ for ad-hoc usage (to avoid having to install anything). Alternatively: continue using the Google schema tools, but use the Google library. Basically: they need to match.
The only minor gotcha here is that protobuf-net does not currently have explicit inbuilt support for DoubleValue; for reference: this can be considered as simply:
namespace Google.Protobuf.WellKnownTypes
{
[ProtoContract]
public sealed class DoubleValue
{
[ProtoMember(1)]
public double Value {get;set;}
}
}
I should probably find time to take all the types from wrappers.proto and allow them as double?, float?, long? etc - but it will need an additional marker, as Nullable<T> is already handled but with a different meaning (i.e. optional in .proto terms)
Related
I am trying to Generically set the Field Values in the ItemsRow class (and others that are similar in format - but properties and fields are different.
I want to do something like what I do with hard coding
public Dictionary<object, Action<T, object>> SetFieldValues = new Dictionary<object, Action<T, object>>
{
{"Description", (m,v) => m.Description = (string)v};
}
public class Mapping<T> where T:Row
{
public Dictionary<object, Action<T, object>> SetFieldValues(string[] headers)
{
Dictionary<object, Action<T, object>> myDict = new Dictionary<object, Action<T, object>>();
// Activator
var objectType = typeof(T); // Type.GetType(T);
var tRow = Activator.CreateInstance(objectType) as Row;
foreach (var item in headers)
{
var myfield = tRow.FindFieldByPropertyName(item);
//myDict[item] = myfield =
//myDict[item] = (m, v) => m.FindFieldByPropertyName(item) = (Type.GetType(myfield.Type.ToString()))v;
}
// I want this to be dynamic header[i],(m,v) => m.(property to set for object) = (cast to type m.property type)v
//{"ItemName", (m,v) => m.ItemName = (string)v},
//{"Description", (m,v) => m.Description = (string)v},
return myDict;
}
// Class names will be different, properties and fields will be different..
public sealed class ItemsRow : Row
{
public String ItemName
{
get { return Fields.ItemName[this]; }
set { Fields.ItemName[this] = value; }
}
public String Description
{
get { return Fields.Description[this]; }
set { Fields.Description[this] = value; }
}
public static readonly RowFields Fields = new RowFields().Init();
public ItemsRow()
: base(Fields)
{
}
public class RowFields : RowFieldsBase
{
public StringField ItemName;
public StringField Description;
}
}
Base Class
=================================================================================
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
namespace Serenity.Data
{
[JsonConverter(typeof(JsonRowConverter))]
public abstract partial class Row : IEntityWithJoins,
INotifyPropertyChanged, IEditableObject
#if !COREFX
, IDataErrorInfo
#endif
{
internal RowFieldsBase fields;
internal bool[] assignedFields;
internal Hashtable dictionaryData;
internal bool ignoreConstraints;
internal object[] indexedData;
internal bool tracking;
internal bool trackWithChecks;
protected Row(RowFieldsBase fields)
{
if (fields == null)
throw new ArgumentNullException("fields");
this.fields = fields.InitInstance(this);
TrackAssignments = true;
}
public void CloneInto(Row clone,
bool cloneHandlers)
{
clone.ignoreConstraints = ignoreConstraints;
foreach (var field in GetFields())
field.Copy(this, clone);
clone.tracking = tracking;
if (tracking)
{
if (assignedFields != null)
{
clone.assignedFields = new bool[assignedFields.Length];
Array.Copy(assignedFields, clone.assignedFields, assignedFields.Length);
}
}
else
clone.assignedFields = null;
clone.trackWithChecks = trackWithChecks;
clone.originalValues = originalValues;
if (dictionaryData != null)
clone.dictionaryData = (Hashtable)this.dictionaryData.Clone();
else
clone.dictionaryData = null;
if (indexedData != null)
{
clone.indexedData = new object[indexedData.Length];
for (var i = 0; i < indexedData.Length; i++)
clone.indexedData[i] = indexedData[i];
}
else
clone.indexedData = null;
if (previousValues != null)
clone.previousValues = previousValues.CloneRow();
else
clone.previousValues = null;
if (cloneHandlers)
{
clone.postHandler = this.postHandler;
clone.propertyChanged = this.propertyChanged;
if (this.validationErrors != null)
clone.validationErrors = new Dictionary<string, string>(this.validationErrors);
else
clone.validationErrors = null;
}
}
public Row CloneRow()
{
var clone = CreateNew();
CloneInto(clone, true);
return clone;
}
public virtual Row CreateNew()
{
if (fields.rowFactory == null)
throw new NotImplementedException();
return fields.rowFactory();
}
internal void FieldAssignedValue(Field field)
{
if (assignedFields == null)
assignedFields = new bool[fields.Count];
assignedFields[field.index] = true;
if (validationErrors != null)
RemoveValidationError(field.PropertyName ?? field.Name);
if (propertyChanged != null)
{
if (field.IndexCompare(previousValues, this) != 0)
{
RaisePropertyChanged(field);
field.Copy(this, previousValues);
}
}
}
public Field FindField(string fieldName)
{
return fields.FindField(fieldName);
}
public Field FindFieldByPropertyName(string propertyName)
{
return fields.FindFieldByPropertyName(propertyName);
}
public RowFieldsBase GetFields()
{
return fields;
}
public int FieldCount
{
get { return fields.Count; }
}
public bool IsAnyFieldAssigned
{
get
{
return tracking && assignedFields != null;
}
}
public bool IgnoreConstraints
{
get { return ignoreConstraints; }
set { ignoreConstraints = value; }
}
public string Table
{
get { return fields.TableName; }
}
public bool TrackAssignments
{
get
{
return tracking;
}
set
{
if (tracking != value)
{
if (value)
{
if (propertyChanged != null)
previousValues = this.CloneRow();
tracking = value;
}
else
{
tracking = false;
trackWithChecks = false;
assignedFields = null;
}
}
}
}
public bool TrackWithChecks
{
get
{
return tracking && trackWithChecks;
}
set
{
if (value != TrackWithChecks)
{
if (value && !tracking)
TrackAssignments = true;
trackWithChecks = value;
}
}
}
private Field FindFieldEnsure(string fieldName)
{
var field = FindField(fieldName);
if (ReferenceEquals(null, field))
throw new ArgumentOutOfRangeException("fieldName", String.Format(
"{0} has no field with name '{1}'.", this.GetType().Name, fieldName));
return field;
}
public object this[string fieldName]
{
get
{
var field = FindFieldByPropertyName(fieldName) ??
FindField(fieldName);
if (ReferenceEquals(null, field))
{
if (dictionaryData != null)
return dictionaryData[fieldName];
return null;
}
return field.AsObject(this);
}
set
{
(FindFieldByPropertyName(fieldName) ??
FindFieldEnsure(fieldName)).AsObject(this, value);
}
}
public void SetDictionaryData(object key, object value)
{
if (value == null)
{
if (dictionaryData == null)
return;
dictionaryData[key] = null;
}
else
{
if (dictionaryData == null)
dictionaryData = new Hashtable();
dictionaryData[key] = value;
}
}
public object GetDictionaryData(object key)
{
if (dictionaryData != null)
return dictionaryData[key];
return null;
}
internal void SetIndexedData(int index, object value)
{
if (value == null)
{
if (indexedData == null)
return;
indexedData[index] = null;
}
else
{
if (indexedData == null)
indexedData = new object[this.FieldCount];
indexedData[index] = value;
}
}
internal object GetIndexedData(int index)
{
if (indexedData != null)
return indexedData[index];
return null;
}
public bool IsAssigned(Field field)
{
if (assignedFields == null)
return false;
return assignedFields[field.index];
}
public void ClearAssignment(Field field)
{
if (assignedFields == null)
return;
assignedFields[field.index] = false;
for (var i = 0; i < assignedFields.Length; i++)
if (assignedFields[i])
return;
assignedFields = null;
}
public bool IsAnyFieldChanged
{
get
{
if (originalValues == null)
return false;
for (var i = 0; i < fields.Count; i++)
if (fields[i].IndexCompare(originalValues, this) != 0)
return true;
return false;
}
}
IDictionary<string, Join> IHaveJoins.Joins
{
get { return fields.Joins; }
}
}
}
Sorry I couldn't get back to you yesterday, but a promise is a promise :). And while writing this code I began to doubt about what your headers actually look like. How are you going to determine which property belongs to which header? Unless you have some type of recognition for that which I might be missing from your code.
But the general idea is this:
Of course this is based on the premise that headers are keyvaluepairs of which the key is the identifier for which property to use.
static void Main(string[] args)
{
var values = new Dictionary<string, string>()
{
["Title"] = "Test",
["Amount"] = "5",
["Description"] = "Some description"
};
var target = new TestClass();
var setters = GetPropertySetters(target);
foreach(KeyValuePair<string, string> value in values)
{
if (setters.ContainsKey(value.Key))
setters[value.Key].Invoke(value.Value);
}
Console.WriteLine(JsonConvert.SerializeObject(target));
Console.ReadLine();
}
public static Dictionary<string, Action<string>> GetPropertySetters<T>(T source)
{
var result = new Dictionary<string, Action<string>>(StringComparer.OrdinalIgnoreCase);
foreach (PropertyInfo pi in typeof(T).GetProperties())
result.Add(pi.Name, (string value) => { pi.SetValue(source, Convert.ChangeType(value, pi.PropertyType)); });
return result;
}
public class TestClass
{
public string Title { get; set; }
public int Amount { get; set; }
public string Description { get; set; }
}
I'm taking over a project on Xamarin.
It work on android and I want it to work on iOS.
Initially, it have been done for that so I expected it work with maybe only settings ?
Anyway it work on Android but not on iOS.
I have this code :
public App()
{
Debug.WriteLine(Current.Properties); //return default value
try
{
ViewModelLocator.MainViewModel.RestoreState(Current.Properties);
BindingContext = ViewModelLocator.MainViewModel;
MainTabPage = new SGC400Tab();
MainPage = MainTabPage;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
public static class ViewModelLocator
{
private static GlobalViewModel _myViewModel = new GlobalViewModel();
public static GlobalViewModel MainViewModel
{
get
{
return _myViewModel;
}
}
}
public class GlobalViewModel : INotifyPropertyChanged
{
public void RestoreState(IDictionary<string, object> dictionary)
{
Thing1.SelectedUnitySystem_Presure = GetDictionaryEntry(dictionary, "SavedUnitySystem_Pression", "Bars");
Thing1.SelectedUnitySystem_Flow = GetDictionaryEntry(dictionary, "SavedUnitySystem_Debit", "m3/h");
Thing1.SelectedUnitySystem_Temperature = GetDictionaryEntry(dictionary, "SavedUnitySystem_Temperature", "°C");
Thing1.SelectedLanguageKey = GetDictionaryEntry(dictionary, "SavedLanguage", "en");
}
}
Which return an error :
System.NullReferenceException on line :
private static GlobalViewModel _myViewModel = new GlobalViewModel();
I'm a bit puzzled by the fact it work on android... but not on iOS...
I have to tell I'm pretty new on Xamarin, may you give me some pointer ?
Thank you in advance !
PS : Class GlobalViewModel here :
public class GlobalViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
//#####################################
//Enneigeur
public Enneigeur _Enneigeur1 = new Enneigeur();
public Enneigeur Enneigeur1
{
get { return _Enneigeur1; }
set
{
_Enneigeur1 = value;
}
}
//Com
public ComSGC400 _comSGC400 = new ComSGC400();
public ComSGC400 ComSGC400
{
get { return _comSGC400; }
set { _comSGC400 = value; }
}
public const int TIMOUT_COM_MS = 500;
public const int DELAI_ENTRE_TRAME_MS = 1000;
//#####################################
//Bluetooth
public ObservableCollection<string> ListOfDevices { get; set; } = new ObservableCollection<string>();
public string inputBuffer;
public string SelectedBthDevice { get;set; } = "";
private bool _isConnected { get; set; } = false;
public bool IsConnected {
get { return _isConnected; }
set
{
_isConnected = value;
if (_isConnected == true)
{
((App)Application.Current).AddPages();
} else
{
((App)Application.Current).RemovePages();
}
}
}
private bool _isSelectedBthDevice { get { if (string.IsNullOrEmpty(SelectedBthDevice)) return false; return true; }}
public bool IsConnectEnabled { get { if (_isSelectedBthDevice == false) return false; return !IsConnected; }}
public bool IsDisconnectEnabled { get { if (_isSelectedBthDevice == false) return false; return IsConnected; } }
public Color ConnectBackgroundcolor { get { if (IsConnectEnabled) return Color.Green; return Color.FromRgb(48, 48, 48); } }
public Color DisconnectBackgroundColor { get { if (IsDisconnectEnabled) return Color.Red; return Color.FromRgb(48, 48, 48); } }
public bool IsConnectionInit { get { if (EtatGrafcet_loop < 2 || IsConnected == false ) return false; return true; } }
public bool IsModeManuOK { get { if (EtatGrafcet_loop >= 2 && IsConnected == true && _Enneigeur1.Manu == true) return true; return false; } }
public bool IsBoutonRotaOK { get { if (EtatGrafcet_loop >= 2 && IsConnected == true && ( _Enneigeur1._VersionSGC400 > 10213 || _Enneigeur1.Manu == true)) return true; return false; } }
public bool IsPickerEnabled { get { return !IsConnected; }}
public bool IsBalayageDispo { get { if (EtatGrafcet_loop < 2 || IsConnected == false || _Enneigeur1.OptionBalayageDispo == false) return false; return true; } }
public LocalizedResources Resources { get; private set;}
public Color Mode_Manu_Button_Text_Color
{
get
{
if (EtatGrafcet_loop < 2)
return Color.Gray;
else
return Color.White;
}
}
public Color Mode_Manu_Button_Color {
get {
if (EtatGrafcet_loop < 2)
return Color.FromRgb(48, 48, 48);
else
{
if (_Enneigeur1.ModeMarche == 1) return Color.Green; return Color.Black;
}
}
}
public Color Mode_Stop_Button_Text_Color
{
get
{
if (EtatGrafcet_loop < 2)
return Color.Gray;
else
return Color.White;
}
}
public Color Mode_Stop_Button_Color {
get
{
if (EtatGrafcet_loop < 2)
return Color.FromRgb(48, 48, 48);
else
{
if (_Enneigeur1.ModeMarche == 2) return Color.Green; return Color.Black;
}
}
}
public Color Mode_Forcage_Button_Text_Color
{
get
{
if (EtatGrafcet_loop < 2)
return Color.Gray;
else
return Color.White;
}
}
public Color Mode_Forcage_Button_Color
{
get
{
if (EtatGrafcet_loop < 2)
return Color.FromRgb(48, 48, 48);
else
{
if (_Enneigeur1.ModeMarche == 0) return Color.Green; return Color.Black;
}
}
}
private CancellationTokenSource _ct { get; set; }
private int EtatGrafcet_loop { get; set; }
private DateTime timer_send = DateTime.Now;
private bool envoiContinu = false;
private string envoiWrite = "";
private async Task Loop()
{
string bufferEnvoi = "";
bool res;
int erreur_cryptage = 0;
EtatGrafcet_loop = 0;
int reponseLen = 0;
_Enneigeur1.ResetValues();
_ct = new CancellationTokenSource();
ComSGC400.AddrSGC400 = Convert.ToUInt16(SelectedBthDevice.Substring(5));
while (_ct.IsCancellationRequested == false)
{
switch (EtatGrafcet_loop)
{
case 0://Envoi trame clé crypté
if (DateTime.Now > timer_send.AddMilliseconds(DELAI_ENTRE_TRAME_MS)) //Temps entre trames
{
//Test d'echange de clé de cryptage
inputBuffer = "";
reponseLen = ComSGC400.Create_Trame_getKey(ref bufferEnvoi);
if (bufferEnvoi.Length > 0)
{
Xamarin.Forms.MessagingCenter.Send<App, string>((App)Xamarin.Forms.Application.Current, "WriteDatas", bufferEnvoi);
timer_send = DateTime.Now;
EtatGrafcet_loop = 1;
}
}
break;
case 1: //attente reception clé crypté
if (DateTime.Now > timer_send.AddMilliseconds(TIMOUT_COM_MS)){ EtatGrafcet_loop = 0; break; } //timeout
if (inputBuffer != null)
{
ComSGC400.Trame_RechercheDebutTrame(ref inputBuffer);
if (inputBuffer.Length >= reponseLen)
{
inputBuffer = inputBuffer.Substring(0, reponseLen);
res = ComSGC400.Update_ProtectionKey( inputBuffer);
if (res == true)
{
//cle cryptage OK
bufferEnvoi = "";
EtatGrafcet_loop = 2;
erreur_cryptage = 0;
}
else
{
//cle cryptage non ok
bufferEnvoi = "";
EtatGrafcet_loop = 0;
}
inputBuffer = "";
}
}
break;
case 2: //envoi trame readMain
if (envoiWrite != "")
EtatGrafcet_loop = 10; //envoi write
else
{
if (DateTime.Now > timer_send.AddMilliseconds(DELAI_ENTRE_TRAME_MS)) //Temps entre trames
{
reponseLen = ComSGC400.Create_Trame_ReadMain(ref bufferEnvoi);
if (bufferEnvoi.Length > 0)
{
inputBuffer = "";
Xamarin.Forms.MessagingCenter.Send<App, string>((App)Xamarin.Forms.Application.Current, "WriteDatas", bufferEnvoi);
timer_send = DateTime.Now;
EtatGrafcet_loop = 3;
}
}
}
break;
case 3: //attente reponse trame readMain
if (DateTime.Now > timer_send.AddMilliseconds(TIMOUT_COM_MS)) {
EtatGrafcet_loop = 20; break;
} //timeout
if (inputBuffer != null)
{
ComSGC400.Trame_RechercheDebutTrame(ref inputBuffer);
if (inputBuffer.Length >= reponseLen)
{
inputBuffer = inputBuffer.Substring(0, reponseLen);
res = ComSGC400.Update_Enneigeur( inputBuffer, ref _Enneigeur1);
if (res == true)
{
//Message OK
bufferEnvoi = "";
EtatGrafcet_loop = 4;//Passage readCom
erreur_cryptage = 0;
_Enneigeur1.LastRead = DateTime.Now;
}
else
{
//Message NON OK
EtatGrafcet_loop = 20;
}
inputBuffer = "";
}
}
break;
case 4: //envoi trame readCom
if (envoiWrite != "")
EtatGrafcet_loop = 10; //envoi write
else
{
if (DateTime.Now > timer_send.AddMilliseconds(50)) //Temps entre trames
{
reponseLen = ComSGC400.Create_Trame_ReadCom(ref bufferEnvoi);
if (bufferEnvoi.Length > 0)
{
inputBuffer = "";
Xamarin.Forms.MessagingCenter.Send<App, string>((App)Xamarin.Forms.Application.Current, "WriteDatas", bufferEnvoi);
timer_send = DateTime.Now;
EtatGrafcet_loop = 5;
}
}
}
break;
case 5: //attente reponse trame readCom
if (DateTime.Now > timer_send.AddMilliseconds(TIMOUT_COM_MS)) {
EtatGrafcet_loop = 21; break;
} //timeout
if (inputBuffer != null)
{
ComSGC400.Trame_RechercheDebutTrame(ref inputBuffer);
if (inputBuffer.Length >= reponseLen)
{
inputBuffer = inputBuffer.Substring(0, reponseLen);
res = ComSGC400.Update_Enneigeur( inputBuffer, ref _Enneigeur1);
if (res == true)
{
//Message OK
bufferEnvoi = "";
EtatGrafcet_loop = 2; //Retour read main
erreur_cryptage = 0;
_Enneigeur1.LastRead = DateTime.Now;
if (_Enneigeur1.Reset)
Send_value_bluetooth("reset", false);
}
else
{
//Message NON OK
EtatGrafcet_loop = 21;
}
inputBuffer = "";
}
}
break;
case 10: //envoi trame Write
inputBuffer = "";
Xamarin.Forms.MessagingCenter.Send<App, string>((App)Xamarin.Forms.Application.Current, "WriteDatas", envoiWrite);
timer_send = DateTime.Now;
EtatGrafcet_loop =11;
break;
case 11: //attente reponse trame Write
if (DateTime.Now > timer_send.AddMilliseconds(TIMOUT_COM_MS)) { EtatGrafcet_loop = 20; break; } //timeout
if (inputBuffer != null)
{
ComSGC400.Trame_RechercheDebutTrame(ref inputBuffer);
if (inputBuffer.Length >= 16)
{
bufferEnvoi = "";
if (envoiContinu)
{
EtatGrafcet_loop = 10; //envoi continu
}
else
{
envoiWrite = "";
EtatGrafcet_loop = 2; //Retour read main
}
erreur_cryptage = 0;
_Enneigeur1.LastWrite = DateTime.Now;
inputBuffer = "";
}
}
break;
case 20://Erreur de reception trame readMain
bufferEnvoi = "";
erreur_cryptage = erreur_cryptage + 1;
envoiWrite = "";
if (erreur_cryptage > 3)
{
_Enneigeur1.ResetValues();
erreur_cryptage = 0;
EtatGrafcet_loop = 0;
}
else
{
EtatGrafcet_loop = 2;
}
break;
case 21://Erreur de reception trame readCom
bufferEnvoi = "";
erreur_cryptage = erreur_cryptage + 1;
envoiWrite = "";
if (erreur_cryptage > 3)
{
_Enneigeur1.ResetValues();
erreur_cryptage = 0;
EtatGrafcet_loop = 0;
}
else
{
EtatGrafcet_loop = 4;
}
break;
default:
EtatGrafcet_loop = 0;
break;
}
await Task.Delay(10);
}
EtatGrafcet_loop = 0;
}
public void Send_value_bluetooth(string nom_param, bool value)
{
if (value == true) Send_value_bluetooth( nom_param, 1); else Send_value_bluetooth(nom_param, 0);
}
public void Send_value_bluetooth(string nom_param, double value)
{
//la modif de Enneigeur1 entraine l'envoi d'une trame WRITE en bluetooth (si la liaison est OK)
string bufferEnvoi = "";
if (EtatGrafcet_loop >= 2)
{
switch(nom_param.ToLower())
{
Cases...
}
}
}
public void ExitApp()
{
// Disconnect from bth device
DependencyService.Get<IBtInterface>().Disconnect();
MessagingCenter.Unsubscribe<App, string>(this, "ReadDatas");
IsConnected = false;
if (_ct != null)
{
System.Diagnostics.Debug.WriteLine("Send a cancel to task!");
_ct.Cancel();
}
}
public GlobalViewModel()
{
Resources = new LocalizedResources(typeof(AppResources), Enneigeur1._SelectedLanguageKey
);
MessagingCenter.Subscribe<App>(this, "Sleep", (obj) =>
{
// When the app "sleep", I close the connection with bluetooth
if (IsConnected)
DependencyService.Get<IBtInterface>().Disconnect();
});
MessagingCenter.Subscribe<App>(this, "Resume", (obj) =>
{
// When the app "resume" I try to restart the connection with bluetooth
if (IsConnected)
DependencyService.Get<IBtInterface>().Connect(SelectedBthDevice);
});
this.InitCommand = new Command(() =>
{
// Try to connect to a bth device
DependencyService.Get<IBtInterface>().Init();
});
this.ConnectCommand = new Command(() =>
{
EtatGrafcet_loop = 0;
// Try to connect to a bth device
IsConnected = DependencyService.Get<IBtInterface>().Connect(SelectedBthDevice);
//second essai
if (IsConnected == false) IsConnected = DependencyService.Get<IBtInterface>().Connect(SelectedBthDevice);
if (IsConnected == true)
{
// initialisation des echange de données
MessagingCenter.Subscribe<App, string>(this, "ReadDatas", (sender, arg) =>
{
//inputBuffer = inputBuffer + arg;
inputBuffer = inputBuffer + arg;
});
Task.Run(async () => Loop());
}else
{
//erreur aux 2 tentatives de connection
//Task.Run(async () => ((App)Application.Current).OpenTextBoxDialog());
((App)Application.Current).OpenTextBoxDialog();
}
});
this.DisconnectCommand = new Command(() =>
{
EtatGrafcet_loop = 0;
ExitApp();
});
this.RefreshListDeviceCommand = new Command(() =>
{
try
{
ListOfDevices = DependencyService.Get<IBtInterface>().PairedDevices();
}
catch (Exception ex)
{
Application.Current.MainPage.DisplayAlert("Attention", ex.Message, "Ok");
}
});
// At startup, I load all paired devices
try
{
ListOfDevices = DependencyService.Get<IBtInterface>().PairedDevices();
}
catch (Exception ex)
{
Application.Current.MainPage.DisplayAlert("Attention", ex.Message, "Ok");
}
}
private object Await(App current)
{
throw new NotImplementedException();
}
public ICommand InitCommand { get; protected set; }
public ICommand ConnectCommand { get; protected set; }
public ICommand DisconnectCommand { get; protected set; }
public ICommand RefreshListDeviceCommand { get; protected set; }
public void SaveState(IDictionary<string, object> dictionary)
{
dictionary["SavedLanguage"] = Enneigeur1._SelectedLanguageKey;
dictionary["SavedUnitySystem_Pression"] = Enneigeur1.SelectedUnitySystem_Presure;
dictionary["SavedUnitySystem_Debit"] = Enneigeur1.SelectedUnitySystem_Flow;
dictionary["SavedUnitySystem_Temperature"] = Enneigeur1.SelectedUnitySystem_Temperature;
}
public void RestoreState(IDictionary<string, object> dictionary)
{
Enneigeur1.SelectedUnitySystem_Presure = GetDictionaryEntry(dictionary, "SavedUnitySystem_Pression", "Bars");
Enneigeur1.SelectedUnitySystem_Flow = GetDictionaryEntry(dictionary, "SavedUnitySystem_Debit", "m3/h");
Enneigeur1.SelectedUnitySystem_Temperature = GetDictionaryEntry(dictionary, "SavedUnitySystem_Temperature", "°C");
Enneigeur1.SelectedLanguageKey = GetDictionaryEntry(dictionary, "SavedLanguage", "en");
}
public T GetDictionaryEntry<T>(IDictionary<string, object> dictionary,
string key, T defaultValue)
{
if (dictionary.ContainsKey(key))
return (T)dictionary[key];
return defaultValue;
}
}
I have to annotate literally hundreds of classes and thousands of methods.
e.g.
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
has to change to
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
How can I go about easily annotating all those classes/methods automatically? FYI.. I do have resharper installed if anyone know how I can use that to assist
Heres my final code that works.
using EnvDTE;
using EnvDTE80;
using System.Windows.Forms;
using System.Diagnostics;
public class C : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
this.DTE = DTE;
AnnotateAllInterfacesAndMethods("Console1");
}
private void AnnotateAllInterfacesAndMethods(string projectName)
{
var res = AllClasses(projectName);
foreach (EnvDTE.CodeInterface c in res)
{
//ADD attributes
if (c.Attributes.Count == 0)
{
c.AddAttribute("System.ServiceModel.ServiceContract", $"Name=\"{c.Name}\"");
}
else
{
bool broken = false;
var items = c.Attributes.GetEnumerator();
while (items.MoveNext())
{
CodeElement value = (CodeElement)items.Current;
if (value.Name == "ServiceContract")
{
broken = true;
break;
}
}
//service contract not found. So we add it.
if (!broken)
{
c.AddAttribute("System.ServiceModel.ServiceContract", $"Name=\"{c.Name}\"");
}
}
if (c.Members.Count > 0)
{
foreach (EnvDTE.CodeElement m in c.Members)
{
if (m.Kind == EnvDTE.vsCMElement.vsCMElementFunction)
{
var func = (m as EnvDTE.CodeFunction);
if (func.Attributes.Count == 0)
{
func.AddAttribute("System.ServiceModel.OperationContract", $"Name=\"{func.Name}\"");
}
else
{
bool broken = false;
var items = func.Attributes.GetEnumerator();
while (items.MoveNext())
{
CodeElement value = (CodeElement)items.Current;
if (value.Name == "OperationContract")
{
broken = true;
break;
}
}
//OperationContract not found. So we add it.
if (!broken)
{
func.AddAttribute("System.ServiceModel.OperationContract", $"Name=\"{func.Name}\"");
}
}
}
}
}
}
System.Windows.MessageBox.Show("Done");
}
private System.Collections.Generic.List<EnvDTE.CodeInterface> AllClasses(string projectName)
{
System.Collections.Generic.List<EnvDTE.CodeInterface> result = new System.Collections.Generic.List<EnvDTE.CodeInterface>();
foreach (EnvDTE.Project p in DTE.Solution.Projects)
{
if (projectName == p.Name)
{
EnumerateProjectItems(p.ProjectItems, result);
}
}
return result;
}
private void EnumerateProjectItems(EnvDTE.ProjectItems items, System.Collections.Generic.List<EnvDTE.CodeInterface> result)
{
foreach (EnvDTE.ProjectItem i in items)
{
if (i.FileCodeModel != null && i.FileCodeModel.CodeElements != null)
{
foreach (EnvDTE.CodeElement n in i.FileCodeModel.CodeElements)
{
if (n.Kind == EnvDTE.vsCMElement.vsCMElementNamespace)
{
foreach (EnvDTE.CodeElement c in (n as EnvDTE.CodeNamespace).Members)
{
if (c.Kind == EnvDTE.vsCMElement.vsCMElementInterface)
{
result.Add(c as EnvDTE.CodeInterface);
}
}
}
}
}
if (i.ProjectItems != null)
EnumerateProjectItems(i.ProjectItems, result);
}
}
private EnvDTE80.DTE2 DTE;
}
You can quickly add an attribute to the current class and its properties with the following Visual Commander command (C#):
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
EnvDTE.TextSelection ts = DTE.ActiveWindow.Selection as EnvDTE.TextSelection;
if (ts == null)
return;
EnvDTE.CodeClass codeClass = ts.ActivePoint.CodeElement[EnvDTE.vsCMElement.vsCMElementClass]
as EnvDTE.CodeClass;
if (codeClass == null)
return;
codeClass.AddAttribute("DataContract", null);
foreach(EnvDTE.CodeElement i in codeClass.Children)
{
if (i is EnvDTE.CodeProperty)
(i as EnvDTE.CodeProperty).AddAttribute("DataMember", null);
}
}
Just position the caret inside a class definition and call the command from the VCmd menu or with a keyboard shortcut.
I'm creating an application in Unity3d that communicates with python's websockets library. My python script is as following:
from __future__ import division
import asyncio
import websockets
import time
import os
from threading import Thread
from random import randint
from read import CustOPCLib
import socket
from jsonsocket import Client,Server
class SubHandler(object):
def data_change(self, handle, node, val, attr):
print("Python: New data change event", handle, node, val, attr)
def datachange_notification(self, node, val, data):
print("Data received: ",val)
def event(self, handle, event):
print("Python: New event", handle, event)
p = CustOPCLib()
async def hello(websocket, path):
p.connect() #my own custom library
while True:
datastring = p.opcjson() #this is a jsonstring
await websocket.send(datastring)
#print("> {}".format(datastring))
time.sleep(1)
if __name__ == '__main__':
start_server = websockets.serve(hello, '127.0.0.1', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
my json string is as following:
{
"Index": 709953575,
"Moto": true,
"Start": false,
"StartWINCC": false,
"Stop": false,
"StopWINCC": false,
"Tag1": true,
"Tag2": false
}
This is the string i want to send to Unity. In Unity3d I've made the following script that used the Concurrentqueue from mono. The script works accordingly, the problem i have however, is that i get alot of null values from the websocket.
my Unity3d script:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading;
public class ConcurrentQueue<T> : IEnumerable<T>, ICollection, ISerializable, IDeserializationCallback
{
class Node
{
public T Value;
public Node Next;
}
Node _head = new Node();
Node _tail;
int _count;
/// <summary>
/// </summary>
public ConcurrentQueue()
{
_tail = _head;
}
public ConcurrentQueue(IEnumerable<T> enumerable)
: this()
{
foreach (T item in enumerable)
Enqueue(item);
}
public void Enqueue(T item)
{
var node = new Node { Value = item };
Node oldTail = null;
bool update = false;
while (!update)
{
oldTail = _tail;
var oldNext = oldTail.Next;
// Did tail was already updated ?
if (_tail == oldTail)
{
if (oldNext == null)
{
// The place is for us
update = Interlocked.CompareExchange(ref _tail.Next, node, null) == null;
}
else
{
// another Thread already used the place so give him a hand by putting tail where it should be
Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
}
}
}
// At this point we added correctly our node, now we have to update tail. If it fails then it will be done by another thread
Interlocked.CompareExchange(ref _tail, node, oldTail);
Interlocked.Increment(ref _count);
}
/// <summary>
/// </summary>
/// <returns></returns>
public bool TryDequeue(out T value)
{
value = default(T);
bool advanced = false;
while (!advanced)
{
Node oldHead = _head;
Node oldTail = _tail;
Node oldNext = oldHead.Next;
if (oldHead == _head)
{
// Empty case ?
if (oldHead == oldTail)
{
// This should be false then
if (oldNext != null)
{
// If not then the linked list is mal formed, update tail
Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
}
value = default(T);
return false;
}
else
{
value = oldNext.Value;
advanced = Interlocked.CompareExchange(ref _head, oldNext, oldHead) == oldHead;
}
}
}
Interlocked.Decrement(ref _count);
return true;
}
/// <summary>
/// </summary>
/// <returns></returns>
public bool TryPeek(out T value)
{
if (IsEmpty)
{
value = default(T);
return false;
}
Node first = _head.Next;
value = first.Value;
return true;
}
public void Clear()
{
_count = 0;
_tail = _head = new Node();
}
IEnumerator IEnumerable.GetEnumerator()
{
return InternalGetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return InternalGetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return InternalGetEnumerator();
}
IEnumerator<T> InternalGetEnumerator()
{
Node myHead = _head;
while ((myHead = myHead.Next) != null)
{
yield return myHead.Value;
}
}
void ICollection.CopyTo(Array array, int index)
{
T[] dest = array as T[];
if (dest == null)
return;
CopyTo(dest, index);
}
public void CopyTo(T[] dest, int index)
{
IEnumerator<T> e = InternalGetEnumerator();
int i = index;
while (e.MoveNext())
{
dest[i++] = e.Current;
}
}
public T[] ToArray()
{
T[] dest = new T[_count];
CopyTo(dest, 0);
return dest;
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new NotImplementedException();
}
bool ICollection.IsSynchronized
{
get { return true; }
}
public void OnDeserialization(object sender)
{
throw new NotImplementedException();
}
readonly object _syncRoot = new object();
object ICollection.SyncRoot
{
get { return _syncRoot; }
}
public int Count
{
get
{
return _count;
}
}
public bool IsEmpty
{
get
{
return _count == 0;
}
}
}
public class test : MonoBehaviour
{
class OpcJson
{
public int Index { get; set; }
public bool Moto { get; set; }
public bool Start { get; set; }
public bool StartWINCC { get; set; }
public bool Stop { get; set; }
public bool StopWINCC { get; set; }
public bool Tag1 { get; set; }
public bool Tag2 { get; set; }
}
//variables
static readonly ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
public string receivedFromServer;
WebSocket w = new WebSocket(new Uri("ws://127.0.0.1:8765"));
public Text testert;
public Image moto;
public Image start;
public Image startwincc;
public Image stop;
public Image stopwincc;
public Image tag1;
public Image tag2;
// Use this for initialization
IEnumerator StartWebsocket()
{
yield return StartCoroutine(w.Connect());
//w.SendString("Hi there");
//int i = 0;
while (true)
{
string reply = w.RecvString();
if (reply != null)
{
//Debug.Log(reply);
queue.Enqueue(reply);
//receivedFromServer = reply;
//Debug.Log("Received: " + reply);
//w.SendString("Hi there" + i++);
}
if (w.error != null)
{
Debug.LogError("Error: " + w.error);
break;
}
yield return 0;
}
w.Close();
}
private void OnApplicationQuit()
{
StopAllCoroutines();
w.Close();
}
IEnumerator JsonObjectSetter(float waitforsecods)
{
while (true)
{
queue.TryDequeue(out receivedFromServer);
//string s = receivedFromServer;
//Debug.Log(s);
if(receivedFromServer == null)
{
Debug.Log("I'm null");
}
else
{
var results = JsonConvert.DeserializeObject<OpcJson>(receivedFromServer);
testert.text = results.Index.ToString();
if (results.Moto == true)
{
moto.GetComponent<Image>().color = Color.green;
}
else
{
moto.GetComponent<Image>().color = Color.red;
}
if (results.Start == true)
{
start.GetComponent<Image>().color = Color.green;
}
else
{
start.GetComponent<Image>().color = Color.red;
}
if (results.StartWINCC == true)
{
startwincc.GetComponent<Image>().color = Color.green;
}
else
{
startwincc.GetComponent<Image>().color = Color.red;
}
if (results.Stop == true)
{
stop.GetComponent<Image>().color = Color.green;
}
else
{
stop.GetComponent<Image>().color = Color.red;
}
if (results.StopWINCC == true)
{
stopwincc.GetComponent<Image>().color = Color.green;
}
else
{
stopwincc.GetComponent<Image>().color = Color.red;
}
if (results.Tag1 == true)
{
tag1.GetComponent<Image>().color = Color.green;
}
else
{
tag1.GetComponent<Image>().color = Color.red;
}
if (results.Tag2 == true)
{
tag2.GetComponent<Image>().color = Color.green;
}
else
{
tag2.GetComponent<Image>().color = Color.red;
}
}
yield return new WaitForSeconds(waitforsecods);
}
}
private void Start()
{
StartCoroutine(StartWebsocket());
StartCoroutine(JsonObjectSetter(1));
}
}
as you can see, I've made an if/else statement in my JsonObjectSetter method. Everytime the string is null after a dequeue, it prints out "I'm null", and if its not null, it gets used to set an image to a color according to the value.
How can i make it so I won't get any nulls anymore?
Edit 1: during a 7-minute test I've counted 49 nulls. This is quite a big issue to be honest...
Fixed it!
The problem was that my python script had a time.sleep() which lasts 1 second, changed it to 0.1, and changed the WaitForSecods in the Unityscript to 0.25f. This totally fixed my problem. Kind of stupid that I didn't think of this before posting it on Stackoverflow.
How to mock this class in nUnit Tests?
public class OpenDataQuery: PagedQuery, IOpenDataQuery
{
private static Dictionary<string, SortItem> m_sortModes;
protected override Dictionary<string, SortItem> SortModes
{
get
{
if (m_sortModes == null)
{
m_sortModes = new Dictionary<string, SortItem>();
AddSortMode(m_sortModes, new SortItem(ObjectExtensions.GetNameFromExpression<OpenDataCategoriesModel, string>(m => m.Name), "Наименование ↑", true) { IsDefault = true });
AddSortMode(m_sortModes, new SortItem(ObjectExtensions.GetNameFromExpression<OpenDataCategoriesModel, string>(m => m.Name), "Наименование ↓"));
}
return m_sortModes;
}
}
public IEnumerable<OpenDataCategoriesModel> OpenDataCategories { get; set; }
public string OpenDataTags { get; set; }
}
and
public abstract class PagedQuery : IPagedQuery
{
private const int DEFAULT_PAGE = 1;
private const int DEFAULT_COUNT = 5;
private int? m_page;
private int? m_count;
private int? m_total;
private string m_sort;
public int? Page
{
get
{
if (m_page == null || m_page <= 0)
{
return DEFAULT_PAGE;
}
return m_page;
}
set { m_page = value; }
}
public int? Count
{
get
{
if (m_count == null || m_count <= 0)
{
return DEFAULT_COUNT;
}
return m_count;
}
set { m_count = value; }
}
public int? Total
{
get
{
if (m_total == null || m_total <= 0)
{
return 0;
}
return m_total;
}
set { m_total = value; }
}
public string SearchQuery { get; set; }
protected virtual Dictionary<string, SortItem> SortModes
{
get { return null; }
}
public string Sort
{
get
{
var sortMode = GetSortMode(m_sort);
if (sortMode == null)
{
var defaultSort = (from i in SortModes where i.Value.IsDefault select i).FirstOrDefault();
if (!string.IsNullOrWhiteSpace(defaultSort.Key))
{
return defaultSort.Key;
}
return (from i in SortModes select i.Key).First();
}
return m_sort;
}
set
{
m_sort = value;
}
}
protected void AddSortMode(Dictionary<string, SortItem> sortModes, SortItem sortItem)
{
sortModes.Add(
String.Format(
"{0}{1}",
sortItem.FieldName.ToLower(),
sortItem.Asc ? "asc" : "desc"
),
sortItem
);
}
private SortItem GetSortMode(string sort)
{
if (SortModes == null || string.IsNullOrWhiteSpace(sort) ||
!SortModes.ContainsKey(sort.ToLower()))
{
return null;
}
return SortModes[sort.ToLower()];
}
public IOrderBy GetOrderBy()
{
var item = GetCurrentSortItem();
if (item == null)
{
return null;
}
if (item.Asc)
{
return new OrderBy(item.FieldName);
}
return new OrderByDesc(item.FieldName);
}
public SortItem GetCurrentSortItem()
{
return GetSortMode(Sort);
}
public Dictionary<string, SortItem> GetSortItems()
{
return SortModes;
}
}
and
public interface IOpenDataQuery : IPagedQuery
{
string OpenDataTags { get; set; }
}
I have some service method, that used openDataQuery class in parameters and in unit test i am trying mock this class, but this doesn't work:
public partial class OpenDataQueryRepository : Mock<OpenDataQuery>
{
public OpenDataQueryRepository(MockBehavior mockBehavior = MockBehavior.Strict)
: base(mockBehavior)
{
var opendataQuery = new Mock<IOpenDataQuery>();
var pagedQuery = opendataQuery.As<IPagedQuery>();
this.Setup(p=>p.GetOpenDataCategoriesMain(pagedQuery.Object,outttl)).Returns(OpenDataCategories);
}
}
I know that i should use Moq.Protected() for protected methods, but i don't know how use it correctly in this case. Please help me.
UPDATE:
I am testing this controller:
public class ODOpenDataController : ODBaseController
{
private readonly IOpenDataProvider m_openDataProvider;
public ODOpenDataController(IOpenDataProvider openDataProvider)
{
m_openDataProvider = openDataProvider;
}
public ActionResult Index(OpenDataQuery query)
{
int total;
query.OpenDataCategories = m_openDataProvider.GetOpenDataCategoriesMain(query, out total)
query.Total = total;
return View(query);
}
}
Test:
[Test]
public void Index_Test()
{
var opendataController = new ODOpenDataController(new OpenDataRepository().Object);
var result = opendataController.Index(new OpenDataQuery()) as ViewResult;
var model = result.Model as OpenDataQuery;
Assert.IsTrue(model.OpenDataCategories.Count() == 1);
}