Projekt

Obecné

Profil

Stáhnout (10.9 KB) Statistiky
| Větev: | Tag: | Revize:
1 c137512e Oto Šťáva
#!/usr/bin/env python
2
"""
3
Pymodbus Server With Updating Thread
4
--------------------------------------------------------------------------
5
6
This is an example of having a background thread updating the
7
context while the server is operating. This can also be done with
8
a python thread::
9
10
    from threading import Thread
11
12
    thread = Thread(target=updating_writer, args=(context,))
13
    thread.start()
14
"""
15
# --------------------------------------------------------------------------- #
16
# import the modbus libraries we need
17
# --------------------------------------------------------------------------- #
18
from pymodbus.server.async import StartTcpServer
19
from pymodbus.device import ModbusDeviceIdentification
20
from pymodbus.datastore import ModbusSequentialDataBlock
21
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
22
23
# --------------------------------------------------------------------------- #
24
# import the twisted libraries we need
25
# --------------------------------------------------------------------------- #
26
from twisted.internet.task import LoopingCall
27
28
# --------------------------------------------------------------------------- #
29
# configure the service logging
30
# --------------------------------------------------------------------------- #
31
import logging
32
logging.basicConfig()
33
log = logging.getLogger()
34
log.setLevel(logging.ERROR)
35
36
# random numbers
37
import random
38
39
# global constants
40
41
# discrete input
42
# poloha klicku
43
BIT_BKEY = 32789
44
# bezpecnostni tlacitko
45
BIT_SAFETY_BTN = 32785
46
47
# holding regs
48
# aktualni poloha
49
REG_X = 32768
50
REG_Y = 32769
51
REG_Z = 32770
52
REG_A = 32771
53
#pozice vektoru, kam se tlaci
54
REG_ACT_X = 32772
55
REG_ACT_Y = 32773
56
REG_ACT_Z = 32774
57
#pozice vektoru, kam se ma tlacit
58
REG_DIR_X = 32776
59
REG_DIR_Y = 32777
60
REG_DIR_Z = 32778
61
62
#data s krivkou
63
REG_INDEX = 32867
64
REG_LEN = 32866
65
REG_DATA = 32868
66
# data s kvalitou cviceni
67
REG_Q_1 = 32780
68
REG_Q_TOT = 32781
69
REG_Q_PART = 32782
70
71
#coils
72
#info bity 
73
BIT_RDY = 32871
74
BIT_PC_TO_PLC = 32869
75
BIT_PLC_TO_PC = 32870
76
BIT_MEASUREMENT_TO_PC = 32874
77
#posun motoru
78
BIT_M_UP = 32788
79
BIT_M_DOWN = 32789
80
# uceni
81
BIT_TEACH = 32780
82
# reset pozice
83
BIT_RESET_POS = 32769
84
# prehravani naucene krivky
85
BIT_BPLAY = 32772
86
#cviceni naucene kriky
87
BIT_BPLAY_ASSIST = 32773
88
#priznak ukonceni jednoho cyklu
89
BIT_PART_FINISHED = 32873
90
#adresy pro testovaci zmenu DI
91
BIT_BKEY_CHANGE = 32950
92
BIT_SBTN_CHANGE = 32951
93
94
# modbus reg
95
MB_CO = 1
96
MB_DI = 2
97
MB_HR = 3
98
MB_IR = 4
99
100
# --------------------------------------------------------------------------- #
101
# define your callback process
102
# --------------------------------------------------------------------------- #
103
def prepareMbRegVals(values):
104
    vals = []
105
    for val in values:
106
        if val < 0:
107
            val = val & 0xFFFF
108
        vals.append(val)
109
    return vals
110
111
def updating_writer(a,):
112
    """ A worker process that runs every so often and
113
    updates live values of the context. It should be noted
114
    that there is a race condition for the update.
115
116
    :param arguments: The input arguments to the call
117
    """
118
    global bit_teach, bit_play, bit_rdy, bit_data_change, bit_motor, learned_curve, index_curve, meas_array
119
    global cycles_no, quality, array_pos
120
121
    reset_pos = [0,0,4000]
122
    
123
    log.debug("updating the context")
124
    context = a[0]
125
    
126
    
127
    brdy = context[0].getValues(MB_CO, BIT_RDY, 1)
128
    data_change = context[0].getValues(MB_CO, BIT_PC_TO_PLC, 2)
129
    measurement_get = context[0].getValues(MB_CO, BIT_MEASUREMENT_TO_PC, 1)
130
    motor = context[0].getValues(MB_CO, BIT_M_UP, 2)
131
    bteach = context[0].getValues(MB_CO, BIT_TEACH, 1)
132
    bplay = context[0].getValues(MB_CO, BIT_BPLAY, 2)
133
134
    if (context[0].getValues(MB_CO, BIT_RESET_POS, 1) == [1]):
135
        print("Position reset")
136
        context[0].setValues(MB_CO, BIT_RESET_POS, [0])
137
        context[0].setValues(MB_HR, REG_X, reset_pos)
138
    if (bteach != bit_teach):
139
        if (bteach == [1]):
140
            bplay = [0, 0]
141
            context[0].setValues(MB_CO, BIT_BPLAY, bplay)
142
            learned_curve = []
143
            array_pos = 0
144
            f = open("krivka.txt")
145
            for line in f:
146
                line.rstrip()
147
                lineStr = line.split(";")
148
                onePoint = [int(i) for i in lineStr]
149
                learned_curve.extend(prepareMbRegVals(onePoint))
150
                print(onePoint)
151
            print(len(learned_curve)//4)
152
        else:
153
            index_curve = 0
154
    if (motor != bit_motor):
155
        if (motor[0] == 1):
156
            print("Nahoru")
157
        elif (motor[1] == 1):
158
            print("Dolu")
159
        else:
160
            print("Zastaveno")
161
    if (bit_data_change != data_change):
162
        if (data_change == [0,0]):
163
            brdy = [0]
164
            context[0].setValues(MB_CO, BIT_RDY, brdy)
165
    if (data_change[0] == 1):
166
        if (bit_rdy != brdy) and (brdy == [1]):
167
            val = context[0].getValues(MB_HR, REG_LEN, 2)
168
            print("<- Len: " + str(val[0]) + ", Index: " + str(val[1]))
169
            points = val[0]-val[1]
170
            if (points > 25):
171
                points = 25
172
            learned_curve.extend(context[0].getValues(MB_HR, REG_DATA, points*4))
173
            brdy = [0]
174
            context[0].setValues(MB_CO, BIT_RDY, brdy)
175
    if (data_change[0] != bit_data_change[0]):
176
        if (data_change[0] == 0):
177
            index_curve = 0
178
            print("curve finish")
179
        else:
180
            bplay = [0, 0]
181
            context[0].setValues(MB_CO, BIT_BPLAY, bplay)
182
            learned_curve = []
183
    if (data_change[1] == 1):
184
        if (brdy == [0]):
185
            index_to = index_curve + 25
186
            if (len(learned_curve)-(index_curve*4) < 100):
187
                index_to = len(learned_curve)//4
188
            context[0].setValues(MB_HR, REG_DATA, learned_curve[index_curve*4:index_to*4])
189
            brdy = [1]
190
            context[0].setValues(MB_HR, REG_LEN, [len(learned_curve)//4])
191
            context[0].setValues(MB_HR, REG_INDEX, [index_curve])
192
            context[0].setValues(MB_CO, BIT_RDY, brdy)
193
            print("-> Len: " + str(len(learned_curve)) + ", Index: " + str(index_curve) + ", to: " + str(index_to))
194
            index_curve += 25
195
            if (index_curve*4 > len(learned_curve)):
196
                context[0].setValues(MB_CO, BIT_PLC_TO_PC, [0])
197
                index_curve = 0
198
    if (measurement_get == [1]):
199
        if (brdy == [0]):
200
            index_to = index_curve + 10
201
            if (len(meas_array)-(index_curve*10) < 100):
202
                index_to = len(meas_array)//10
203
            context[0].setValues(MB_HR, REG_DATA, meas_array[index_curve*10:index_to*10])
204
            brdy = [1]
205
            context[0].setValues(MB_HR, REG_LEN, [len(meas_array)//10])
206
            context[0].setValues(MB_HR, REG_INDEX, [index_curve])
207
            context[0].setValues(MB_CO, BIT_RDY, brdy)
208
            print("-> Len: " + str(len(meas_array)) + ", Index: " + str(index_curve) + ", to: " + str(index_to))
209
            index_curve += 10
210
            if (index_curve*10 > len(learned_curve)):
211
                context[0].setValues(MB_CO, BIT_MEASUREMENT_TO_PC, [0])
212
                index_curve = 0
213
            print("measure")
214
    if (bplay != bit_play):
215
        cycles_no = 0
216
        array_pos = 0
217
        quality = [0,0,0]
218
    if (bit_play[1] == 1):
219
        onePoint = learned_curve[array_pos*4:array_pos*4+3]
220
        context[0].setValues(MB_HR, REG_X, onePoint)
221
        
222
        values = [random.randint(-500,500),random.randint(-500,500),random.randint(-200,200),0]
223
        onePoint = prepareMbRegVals(values)
224
        context[0].setValues(MB_HR, REG_ACT_X, onePoint)
225
        values = [random.randint(-200,200),random.randint(-200,200),random.randint(-70,70),0]
226
        onePoint = prepareMbRegVals(values)
227
        context[0].setValues(MB_HR, REG_DIR_X, onePoint)
228
        cycles_no += 1
229
        array_pos += 3
230
        if (array_pos*4 > len(learned_curve)):
231
            array_pos = 0
232
        if (array_pos == 0):
233
            quality[0] = (random.randint(45,100));
234
            context[0].setValues(MB_CO, BIT_PART_FINISHED, [1])
235
        if (cycles_no%25 == 0):
236
            quality[1] = (random.randint(45,100));
237
        quality[2] = (random.randint(45,100));
238
        context[0].setValues(MB_HR, REG_Q_1, quality)
239
    else:
240
        if (bteach == [1]):
241
            #learned_curve.extend(onePoint);
242
            onePoint = learned_curve[array_pos*4:array_pos*4+4]
243
            context[0].setValues(MB_HR, REG_X, onePoint)
244
            array_pos += 8
245
            if (array_pos > len(learned_curve)//4):
246
                context[0].setValues(MB_CO, BIT_TEACH, [0])
247
        else:
248
            values = [random.randint(-1000,1000),random.randint(-1000,1000),random.randint(5000,8000),0]
249
            onePoint = prepareMbRegVals(values)
250
            context[0].setValues(MB_HR, REG_X, onePoint)
251
            context[0].setValues(MB_HR, REG_X, reset_pos)
252
    
253
    #test: set input register using testing coils
254
    #bkey_change = context[0].getValues(MB_CO, BIT_BKEY_CHANGE, 2)
255
    bkey_change = [1,1]
256
    context[0].setValues(MB_DI, BIT_BKEY, [bkey_change[0]])
257
    context[0].setValues(MB_DI, BIT_SAFETY_BTN, [bkey_change[1]])
258
        
259
    bit_rdy = brdy
260
    bit_data_change = data_change
261
    bit_motor = motor
262
    bit_teach = bteach
263
    bit_play = bplay
264
265
def run_updating_server():
266
    # ----------------------------------------------------------------------- # 
267
    # initialize your data store
268
    # ----------------------------------------------------------------------- # 
269
    
270
    store = ModbusSlaveContext(
271
        di=ModbusSequentialDataBlock(32768, [0]*200),
272
        co=ModbusSequentialDataBlock(32768, [0]*200),
273
        hr=ModbusSequentialDataBlock(32768, [0]*200),
274
        ir=ModbusSequentialDataBlock(32768, [0]*200),zero_mode=True)
275
    context = ModbusServerContext(slaves=store, single=True)
276
277
    store.setValues(MB_DI, BIT_SAFETY_BTN, [1])
278
    store.setValues(MB_DI, BIT_BKEY, [1])
279
    # ----------------------------------------------------------------------- # 
280
    # initialize the server information
281
    # ----------------------------------------------------------------------- # 
282
    identity = ModbusDeviceIdentification()
283
    identity.VendorName = 'pymodbus'
284
    identity.ProductCode = 'PM'
285
    identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
286
    identity.ProductName = 'pymodbus Server'
287
    identity.ModelName = 'pymodbus Server'
288
    identity.MajorMinorRevision = '1.0'
289
290
    # ----------------------------------------------------------------------- # 
291
    # run the server you want
292
    # ----------------------------------------------------------------------- # 
293
    time = 0.333  # 333 mseconds delay
294
    loop = LoopingCall(f=updating_writer, a=(context,))
295
    loop.start(time, now=False) # initially delay by time
296
    StartTcpServer(context, identity=identity, address=("localhost", 1502))
297
298
299
bit_teach = 0
300
bit_rdy = [0]
301
bit_data_change = [0,0]
302
bit_motor = [0,0]
303
bit_play = [0,0]
304
learned_curve = []
305
index_curve = 0
306
cycles_no = 0
307
array_pos = 0
308
quality = [0,0,0]
309
# vytvoreni pole s hodnotami mereni #
310
meas_array = [(j) for j in range(270)]
311
312
313
if __name__ == "__main__":
314
    run_updating_server()