MinerMessageSchema.make_minermessage()   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 26
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 20
nop 2
dl 0
loc 26
rs 8
c 0
b 0
f 0
1
'''# Full Cycle Mining Messages'''
2
import json
3
from marshmallow import Schema, fields, post_load
4
from messaging.schema import MinerCommandSchema, MinerSchema, MinerStatsSchema, MinerCurrentPoolSchema
5
from domain.mining import Miner, MinerCommand
6
7
class MessageSchema(Schema):
8
    '''schema for message'''
9
    timestamp = fields.DateTime()
10
    sender = fields.Str()
11
    type = fields.Str()
12
    body = fields.Str()
13
    version = fields.Str()
14
15
    #def make_user(self, data):
16
    #    return User(**data)
17
18
    @post_load
19
    def make_message(self, data):
20
        '''reconstitute a message'''
21
        msg = Message(data['timestamp'], data['sender'], data['type'], data['body'])
22
        return msg
23
24
class MinerCommandMessage(object):
25
    """Command that could be sent to a miner"""
26
    def __init__(self, command='', parameter=''):
27
        self.command = command
28
        self.parameter = parameter
29
30
class MinerMessage(object):
31
    """ Miner information for a message
32
    Miner could be None, meaning message is for all
33
    command could be None, meaning message is informational for a specific miner
34
    """
35
    def __init__(self, miner, command=None, minerstats=None, minerpool=None):
36
        self.command = command
37
        self.miner = miner
38
        self.minerstats = minerstats
39
        self.minerpool = minerpool
40
41
class MinerMessageSchema(Schema):
42
    '''schema for minermessage'''
43
    command = fields.Nested(MinerCommandSchema)
44
    miner = fields.Nested(MinerSchema)
45
    minerstats = fields.Nested(MinerStatsSchema)
46
    minerpool = fields.Nested(MinerCurrentPoolSchema)
47
48
    @post_load
49
    def make_minermessage(self, data):
50
        '''reconstitute a minermessage'''
51
        miner = None
52
        command = None
53
        minerstats = None
54
        minerpool = None
55
        if 'miner' in data:
56
            #miner comes in as dict instead of entity when there is an error in the schema
57
            if isinstance(data['miner'], Miner):
58
                miner = data['miner']
59
            else:
60
                miner = Miner(**data['miner'])
61
        if 'command' in data:
62
            if isinstance(data['command'], MinerCommand):
63
                command = data['command']
64
            else:
65
                command = MinerCommand(**data['command'])
66
        if 'minerstats' in data:
67
            #minerstats = MinerStatistics(Miner=miner,**data['minerstats'])
68
            minerstats = data['minerstats']
69
        if 'minerpool' in data:
70
            #minerpool = MinerCurrentPool(Miner=miner, **data['minerpool'])
71
            minerpool = data['minerpool']
72
        entity = MinerMessage(miner, command, minerstats, minerpool)
73
        return entity
74
75
76
class Message(object):
77
    """A Full Cycle Mining Message
78
    Keep generic so that body can be almost anything
79
    A generic message envelope
80
    See http://marshmallow.readthedocs.io/en/latest/extending.html
81
    """
82
    def __init__(self, timestamp, sender='', message_type='', body='', version=1.1):
83
        self.version = version
84
        self.timestamp = timestamp
85
        self.sender = sender
86
        self.type = message_type
87
        self.body = body
88
89
    def jsonserialize(self, sch, msg):
90
        '''json serialize a message'''
91
        return json.dumps(sch.dump(msg))
92
93
    def bodyjson(self):
94
        '''for some reason it gets encoded as list. just return first element'''
95
        #todo: test why python serialization makes it a list but node does not
96
        jsonlist = json.loads(self.body)
97
        if 'miner' in jsonlist:
98
            return jsonlist
99
        if not isinstance(jsonlist, list):
100
            return jsonlist
101
        return jsonlist[0]
102
103
    def bodyonlyjson(self):
104
        '''deserialize body of message'''
105
        jsononly = json.loads(self.body)
106
        return jsononly
107
108
    def make_any(self, message_type, body):
109
        '''make a message'''
110
        self.type = message_type
111
        self.body = body
112
        return self
113
114
    def make_minerstats(self, miner, minerstats=None, minerpool=None):
115
        '''make a miner stats message'''
116
        self.type = 'minerstats'
117
        minermsg = MinerMessage(miner, command=None, minerstats=minerstats, minerpool=minerpool)
118
        self.body = self.jsonserialize(MinerMessageSchema(), minermsg)
119
        return self
120
121
    def make_command(self, command):
122
        '''make a command message'''
123
        self.type = 'command'
124
        msg = MinerCommandMessage(command.command, command.parameter)
125
        self.body = self.jsonserialize(MinerCommandSchema(), msg)
126
        return self
127
128
    def make_minercommand(self, miner, command):
129
        '''make a miner commad message'''
130
        self.type = 'minercommand'
131
        minermsg = MinerMessage(miner, command=command)
132
        self.body = self.jsonserialize(MinerMessageSchema(), minermsg)
133
        return self
134
135
    #these will handled independently
136
    #def make_sensorvalue(self, sensorvalue):
137
    #    self.type = 'sensorvalue'
138
    #    msg = SensorValueMessage(sensor.sensorid, sensor.value)
139
    #    self.body = self.jsonserialize(SensorValueSchema(),msg)
140
    #    return self
141
142
    #def make_sensor(self, sensor):
143
    #    self.type = 'sensor'
144
    #    msg = SensorMessage(sensor.sensorid, sensor.value)
145
    #    self.body = self.jsonserialize(SensorSchema(),msg)
146
    #    return self
147
148
class ConfigurationMessage(object):
149
    """ A configuration message
150
    Used to save full cycle configuration values
151
    example: command = 'save', entity='pool', id={"poolid":"1"}, values = [{"name":"my pool"}]
152
    """
153
    def __init__(self, command=None, parameter=None, entity=None, configuration_message_id=None, values=None):
154
        self.command = command
155
        self.parameter = parameter
156
        self.entity = entity
157
        self.configuration_message_id = configuration_message_id
158
        self.values = values
159
160
class ConfigurationMessageSchema(Schema):
161
    '''schema for Configuration Message'''
162
    command = fields.Str()
163
    parameter = fields.Str()
164
    entity = fields.Str()
165
    configuration_message_id = fields.Dict()
166
    values = fields.List(fields.Dict())
167
168
    @post_load
169
    def make_configurationmessage(self, data):
170
        '''reconstitute a configurationmessage'''
171
        if isinstance(data, ConfigurationMessage):
172
            return data
173
        command = None
174
        parameter = None
175
        entity = None
176
        configuration_message_id = None
177
        values = None
178
        command = data['command']
179
        if 'parameter' in data:
180
            parameter = data['parameter']
181
        entity = data['entity']
182
        if 'configuration_message_id' in data:
183
            configuration_message_id = data['configuration_message_id']
184
        if 'values' in data:
185
            values = data['values']
186
        msg = ConfigurationMessage(command, parameter, entity, configuration_message_id, values)
187
        return msg
188