Android Question How to 'de-serialization' on c# code?

amorosik

Expert
Licensed User
I am working on a project that includes a B4J procedure and a B4A app that communicate with each other using Mosquitto as an Mqtt server
From Android to send messages I use the classic
B4X:
Dim payload as string="messaggio da spedire"
mqtt_client.Publish (topic, serializator.ConvertObjectToBytes (payload))
And vice versa on the B4J procedure for receiving use
B4X:
Dim obj As Object = serializator.ConvertBytesToObject (Payload)
Dim s As String = obj
So between Android and PC everything works correctly
We must now create a 'viewer' of the mqtt messages and we have been expressly asked in c# why it will then have to be used by other operators who will integrate it into other systems.
We would like to keep the communication as it is now, and simply adapt the c# code to 'understand' the messages sent
The question is: how to make the serializator.ConvertBytesToObject in c#?
Is there a similar functionality in the Dot Net environment or is it necessary to redo it with code shots?
 

amorosik

Expert
Licensed User
I've try to use dll for dot net serialization, but not obtain what i expect
First i added a new class to my c# project, name file clsB4XSerializator.cs

Nome file clsB4XSerializator.cs:
using System;
using System.Collections.Generic;
using System.Text;

using System.Globalization;
using System.IO;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace Mqtt_Client
{
    public class B4XSerializator
    {
        private const byte T_NULL = 0, T_STRING = 1, T_SHORT = 2, T_INT = 3, T_LONG = 4, T_FLOAT = 5,
            T_DOUBLE = 6, T_BOOLEAN = 7, T_BYTE = 10, T_CHAR = 14, T_MAP = 20, T_LIST = 21,
            T_NSARRAY = 22, T_NSDATA = 23, T_TYPE = 24;
        private BinaryReader br;
        private BinaryWriter bw;
        private readonly UTF8Encoding utf8;
        public B4XSerializator()
        {
            utf8 = new UTF8Encoding(false);
        }

        public Object ConvertBytesToObject(byte[] Bytes)
        {
            using (InflaterInputStream inf = new InflaterInputStream(new MemoryStream(Bytes)))
            {
                br = new BinaryReader(inf);
                Object ret = readObject();
                return ret;
            }

        }
        public byte[] ConvertObjectToBytes(Object Object)
        {
            MemoryStream ms = new MemoryStream();
            using (DeflaterOutputStream def = new DeflaterOutputStream(ms))
            {
                bw = new BinaryWriter(def);
                writeObject(Object);
            }
            return ms.ToArray();
        }
        private void writeObject(Object o)
        {
            if (o == null)
                writeByte(T_NULL);
            else if (o is int)
            {
                writeByte(T_INT);
                writeInt((int)o);
            }
            else if (o is Double)
            {
                writeByte(T_DOUBLE);
                bw.Write((double)o);
            }
            else if (o is float)
            {
                writeByte(T_FLOAT);
                bw.Write((float)o);
            }
            else if (o is long)
            {
                writeByte(T_LONG);
                bw.Write((long)o);
            }
            else if (o is byte)
            {
                writeByte(T_BYTE);
                bw.Write((byte)o);
            }
            else if (o is short)
            {
                writeByte(T_SHORT);
                bw.Write((short)o);
            }
            else if (o is Char)
            {
                writeByte(T_CHAR);
                bw.Write((short)(char)o);
            }
            else if (o is bool)
            {
                writeByte(T_BOOLEAN);
                writeByte((byte)((bool)o ? 1 : 0));
            }
            else if (o is string)
            {
                byte[] temp = utf8.GetBytes((string)o);
                writeByte(T_STRING);
                writeInt(temp.Length);
                bw.Write(temp, 0, temp.Length);
            }
            else if (o is List<object>)
            {
                writeByte(T_LIST);
                writeList((List<Object>)o);
            }
            else if (o is Dictionary<object, object>)
            {
                writeByte(T_MAP);
                writeMap((Dictionary<object, object>)o);
            }
            else if (o.GetType().IsArray)
            {
                if (o is byte[])
                {
                    writeByte(T_NSDATA);
                    byte[] b = (byte[])o;
                    writeInt(b.Length);
                    bw.Write(b, 0, b.Length);
                }
                else if (o is object[])
                {
                    writeByte(T_NSARRAY);
                    writeList(new List<object>((object[])o));
                }
                else
                    throw new Exception("Only arrays of bytes or objects are supported.");
            }
            else if (o is B4XType)
            {
                writeByte(T_TYPE);
                writeType((B4XType)o);

            }
            else
                throw new Exception("Type not supported: " + o.GetType());
        }
        private void writeMap(Dictionary<object, object> m)
        {
            writeInt(m.Count);
            foreach (KeyValuePair<object, object> kvp in m)
            {
                writeObject(kvp.Key);
                writeObject(kvp.Value);
            }
        }

        private void writeList(List<object> list)
        {
            writeInt(list.Count);
            foreach (Object o in list)
            {
                writeObject(o);
            }

        }

        private Object readObject()
        {
            byte t = br.ReadByte();
            int len;
            byte[] b;
            switch (t)
            {
                case T_NULL:
                    return null;
                case T_INT:
                    return readInt();
                case T_SHORT:
                    return readShort();
                case T_LONG:
                    return br.ReadInt64();
                case T_FLOAT:
                    return br.ReadSingle();
                case T_DOUBLE:
                    return br.ReadDouble();
                case T_BOOLEAN:
                    return br.ReadByte() == 1;
                case T_BYTE:
                    return br.ReadByte();
                case T_STRING:
                    len = readInt();
                    b = br.ReadBytes(len);
                    return utf8.GetString(b);
                case T_CHAR:
                    return (char)readShort();
                case T_LIST:
                    return readList();
                case T_MAP:
                    return readMap();
                case T_NSDATA:
                    len = readInt();
                    return br.ReadBytes(len);
                case T_NSARRAY:
                    List<Object> list = readList();
                    return list.ToArray();
                case T_TYPE:
                    return readType();
                default:
                    throw new Exception("Unsupported type: " + t);
            }
        }
        private void writeByte(byte b)
        {
            bw.Write(b);
        }
        private void writeInt(int i)
        {
            bw.Write(i);
        }
        private List<Object> readList()
        {
            int len = readInt();
            List<object> arr = new List<object>(len);
            for (int i = 0; i < len; i++)
                arr.Add(readObject());
            return arr;
        }
        private Dictionary<Object, Object> readMap()
        {
            int len = readInt();
            Dictionary<object, object> mm = new Dictionary<object, object>();
            for (int i = 0; i < len; i++)
            {
                mm[readObject()] = readObject();
            }
            return mm;
        }
        private int readInt()
        {
            return br.ReadInt32();
        }
        private short readShort()
        {
            return br.ReadInt16();
        }
        private Object readType()
        {
            string cls = (string)readObject();
            var data = readMap();
            return new B4XType(cls, data);
        }
        private void writeType(B4XType t)
        {
            writeObject("_" + t.ClassName);
            writeMap(t.Fields);
        }

    }
    public class B4XType
    {
        public readonly string ClassName;
        public readonly Dictionary<object, object> Fields;
        public B4XType(string className, Dictionary<object, object> data)
        {
            int i = className.LastIndexOf("$");
            if (i > -1)
                className = className.Substring(i + 2);
            else if (className.StartsWith("_"))
            {
                className = className.Substring(1);
            }
            else
                className = className.ToLower(new CultureInfo("en-US", false));
            this.ClassName = className;
            this.Fields = data;
        }
    }
}

Then, i modify the receive message sub like this
B4X:
private void EventPublishReceived(Object sender, uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishEventArgs e)
        {
            B4XSerializator msg_serialized = new B4XSerializator();
           
            try
            {
                byte[] msg_byte ;
                msg_byte =  msg_serialized.ConvertObjectToBytes(e.Message);
                string messaggio_in_chiaro = Encoding.UTF8.GetString(msg_byte, 0, msg_byte.Length);
            }
            catch (InvalidCastException ex)            {
                Console.Write(ex);
            }
        }

Message is received but is not clear to read, like i expect
I expect that 'messaggio_in_chiaro' to be exactly the string i sent
Where can i search/modify to obtain the string sent ?
 
Upvote 0

amorosik

Expert
Licensed User
No reason to post its code.

You should covert the bytes to object.

B4X:
private void EventPublishReceived(Object sender, uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishEventArgs e)
        {
            B4XSerializator msg_serialized = new B4XSerializator();   

            try
            {
                Object msg_object = msg_serialized.ConvertBytesToObject(e.Message); // ConvertObjectToBytes(e.Message);
                string messaggio_in_chiaro = msg_object.ToString();
            }
            catch (InvalidCastException ex)            {
                Console.Write(ex);
            }
        }


Also with above code, an error appear con clsB4XSerializator code
Wich instruction exactly need to use on c# side to receive, as string, an mqtt message sent after B4A serialization code?


aaa_errore_sharp_zip.jpg
 
Upvote 0

amorosik

Expert
Licensed User
What is the type of e.Message?
Log it as hex to better understand the content. You can compare it to the payload sent in B4A. Use ByteConverter.HexFromBytes in B4A.

e.Message is byte[] (array of byte)
I honestly can't really figure out where the anomaly is

aaa_mqtt_ser_prob1.jpg
 
Upvote 0
Top