├── images ├── test.png └── Pydroid_3_Screenshot_A51.png ├── test.py ├── protocol.txt ├── LICENSE ├── sample_multipacket.md ├── sample_with_error.md ├── compare_read_diag.md ├── README.md └── pyfanuc.py /images/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diohpix/pyfanuc/HEAD/images/test.png -------------------------------------------------------------------------------- /images/Pydroid_3_Screenshot_A51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diohpix/pyfanuc/HEAD/images/Pydroid_3_Screenshot_A51.png -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from pyfanuc import pyfanuc 3 | 4 | conn=pyfanuc('192.168.0.61') 5 | if conn.connect(): 6 | print("Verbunden") 7 | print("Lese SPS-Wert D2204 als 16 Bit") 8 | n=conn.readpmc(1,9,2204,1) 9 | if n is not None: 10 | print("Leitwert %0.1f" % (n[2204]/48)) 11 | print("Lese SPS-Wert D1870 & 1874 als 32 Bit") 12 | n=conn.readpmc(2,9,1870,2) 13 | if n is not None: 14 | print("Laenge: %i von %i (%0.1f %%)" % (n[1870],n[1874],n[1870]/n[1874]*100)) 15 | print("Lese Achsen") 16 | for key,val in conn.readaxis(conn.ABS | conn.SKIP | conn.REL | conn.REF).items(): 17 | print(key,val) 18 | print("Lese Programm O5555") 19 | print(conn.getprog("O5555")) 20 | -------------------------------------------------------------------------------- /protocol.txt: -------------------------------------------------------------------------------- 1 | 01,01,0e Read CNCParam 2 | 01,01,15 Read Macro 3 | 01,01,16 Set Macro 4 | 01,01,18 SysInfo 5 | 01,01,1a readalarm 6 | 01,01,1c Read Prgnum Main/Run 7 | 01,01,1d Read SeqNum 8 | 01,01,1f Rewind 9 | 01,01,20 Read MDI 10 | 11 | 01,01,21 Read GCode(s) 12 | 13 | 01,01,23 Read Alarminfo 14 | 01,01,24 Read act Feedrate 15 | 01,01,25 Read act SpindleSpeed (acts) 16 | 01,01,26 Read Position 17 | 18 | 01,01,30 Read Diag 19 | 20 | 01,01,40 Read act SpindleSpeed/-Load (acts2) 21 | 01,01,45 get time/date 22 | 01,01,46 set time/date 23 | 01,01,56 servo load MAX_AXIS 24 | 25 | 01,01,61 read signal names operator panel 26 | 27 | 01,01,88 ?? 28 | 01,01,89 axis names 29 | 01,01,8a spindle names 30 | 01,01,8b axis names ( absolute spindle ) 31 | 01,01,8d read CNC param (cnc_rdparam3) 32 | 33 | 01,01,96 read GCode (30i) 34 | 01,01,a0 read Param info 35 | 01,01,a2 read Diag info 36 | 01,01,a4 (controlled axis 0/spindle 1) 37 | 01,01,a7 read macro (double) 38 | 39 | 01,01,b0 read current directory (FULLNAME i31) 40 | 01,01,b3 read directory entrys (FULLNAME i31) 41 | 01,01,b4 read directory entry count (FULLNAME i31) 42 | 01,01,b9 read main program name (FULLNAME i31) 43 | 44 | 02,01,8001 read PMC 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /sample_multipacket.md: -------------------------------------------------------------------------------- 1 | request: 2 | 3 |
 4 | a0 a0 a0 a0 00 01 21 01
 5 | 	00 72 [length]
 6 | 		00 04 [4 subpackets]
 7 | 			00 1c [length subpacket 1]
 8 | 				00 01 00 01 00 a4 [get controlled axis]
 9 | 					00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 | 			00 1c [length subpacket 2]
11 | 				00 01 00 01 00 89 [get axis names]
12 | 					00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
13 | 			00 1c [length subpacket 3]
14 | 				00 01 00 01 00 56 [get servo load]
15 | 					00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16 | 			00 1c [length subpacket 4]
17 | 				00 01 00 01 00 a4 [get controlled axis]
18 | 					00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
19 | 
20 | 21 | response: 22 | 23 |
24 | a0 a0 a0 a0 00 04 21 02
25 | 	01 56
26 | 		00 04
27 | 			00 12
28 | 				00 01 00 01 00 a4 00 00 00 00 00 00
29 | 					00 02 [length payload]
30 | 						00 04 [4 controlled axes]
31 | 			00 20
32 | 				00 01 00 01 00 89 00 00 00 00 00 00
33 | 					00 10 [length payload]
34 | 						58 00 00 00 59 00 00 00 5a 00 00 00 42 00 00 00 ['X' 'Y' 'Z' 'B']
35 | 			01 10
36 | 				00 01 00 01 00 56 00 00 00 00 00 00
37 | 					01 00 [length payload]
38 | 						00 00 00 00 00 0a 00 00 ff ff ff fd 00 0a 00 00 [32 (MAX_AXIS) values]
39 | 						00 00 00 21 00 0a 00 00 00 00 00 00 00 0a 00 00
40 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
41 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
42 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
43 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
44 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
45 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
46 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
47 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
48 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
49 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
50 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
51 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
52 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
53 | 						00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 00 00
54 | 			00 12
55 | 				00 01 00 01 00 a4 00 00 00 00 00 00
56 | 					00 02 [length payload]
57 | 						00 04 [4 controlled axes]
58 | 
59 | -------------------------------------------------------------------------------- /sample_with_error.md: -------------------------------------------------------------------------------- 1 | # request 2 |
 3 | a0 a0 a0 a0 00 01 21 01
 4 | 	00 fe [length]
 5 | 		00 09 [9 subpackets]
 6 | 			00 1c [subpacket 1 length]
 7 | 				00 01 00 01 00 1a
 8 | 				00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ALARM]
 9 | 			00 1c [subpacket 2 length]
10 | 				00 01 00 01 00 1c
11 | 				00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ACT RUN/MAIN]
12 | 			00 1c [subpacket 3 length]
13 | 				00 01 00 01 00 1d
14 | 				00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ACT SEQ]
15 | 			00 1c [subpacket 4 length]
16 | 				00 01 00 01 00 24
17 | 				00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ACTF]
18 | 			00 1c [subpacket 5 length]
19 | 				00 01 00 01 00 25
20 | 				00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ACTS]
21 | 			00 1c [subpacket 6 length]
22 | 				00 01 00 01 00 26
23 | 				00 00 00 04 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 [POS ABS]
24 | 			00 1c [subpacket 7 length]
25 | 				00 01 00 01 00 26
26 | 				00 00 00 01 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 [POS REF(MACHINE)]
27 | 			00 1c [subpacket 8 length]
28 | 				00 01 00 01 00 26
29 | 				00 00 00 06 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 [POS REL]
30 | 			00 1c [subpacket 9 length]
31 | 				00 01 00 01 00 26
32 | 				00 00 00 07 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 [POS REMAIN DIST]
33 | 
34 | # response 35 |
36 | a0 a0 a0 a0 00 02 21 02
37 | 	01 6a [length]
38 | 		00 09 [9 subpackets]
39 | 			00 14 [subpacket 1 length]
40 | 				00 01 00 01 00 1a 00 00 00 00 00 00 [ok - no error]
41 | 					00 04 [payload length]
42 | 						00 00 00 00 [no alarm]
43 | 			00 18 [subpacket 2 length]
44 | 				00 01 00 01 00 1c 00 00 00 00 00 00 [ok - no error]
45 | 					00 08 [payload length]
46 | 						00 00 0b b8 00 00 0b b8 [running and main O3000]
47 | 			00 14 [subpacket 3 length]
48 | 				00 01 00 01 00 1d 00 00 00 00 00 00 [ok - no error]
49 | 					00 04 [payload length]
50 | 						00 00 00 00	[active seq 0]
51 | 			00 18 [subpacket 4 length]
52 | 				00 01 00 01 00 24 00 00 00 00 00 00
53 | 					00 08 [payload length]
54 | 						00 00 00 00 00 0a 00 04 [feedrate 0]
55 | 			00 10 [subpacket 5 length]
56 | 				00 01 00 01 00 25 00 01 00 00 00 00 00 00 [error #1 function not implemented]
57 | 			00 50 [subpacket 6 length]
58 | 				00 01 00 01 00 26 00 00 00 00 00 00 [ok - no error]
59 | 					00 40 [payload length]
60 | 						00 2f 7a e9 00 0a 00 04 00 02 bc 02 00 0a 00 04
61 | 						00 00 00 00 00 0a 00 04 00 00 00 00 00 0a 00 04
62 | 						ff ec ed 30 00 0a 00 04 00 36 ee 80 00 0a 00 04
63 | 						00 00 00 00 00 0a 00 04 00 00 00 00 00 0a 00 04
64 | 			00 50 [subpacket 7 length]
65 | 				00 01 00 01 00 26 00 00 00 00 00 00 [ok - no error]
66 | 					00 40 [payload length]
67 | 						ff fd b0 bd 00 0a 00 04 ff ed 51 11 00 0a 00 04
68 | 						ff ff f7 ad 00 0a 00 04 ff ff ff 9d 00 0a 00 04
69 | 						ff ec ed 30 00 0a 00 04 00 32 2a 47 00 0a 00 04
70 | 						00 00 00 00 00 0a 00 04 00 00 00 00 00 0a 00 04
71 | 			00 50 [subpacket 8 length]
72 | 				00 01 00 01 00 26 00 00 00 00 00 00 [ok - no error]
73 | 					00 40 [payload length]
74 | 						00 16 d1 05 00 0a 00 04 00 04 78 0b 00 0a 00 04
75 | 						ff ff fe 62 00 0a 00 04 00 00 10 af 00 0a 00 04
76 | 						00 0a e5 67 00 0a 00 04 e4 18 b6 0e 00 0a 00 04
77 | 						00 00 00 00 00 0a 00 04 00 00 00 00 00 0a 00 04
78 | 			00 10 [subpacket 9 length]
79 | 				00 01 00 01 00 26 00 06 00 00 00 00 00 00 [error #6 option error]
80 | 
81 | -------------------------------------------------------------------------------- /compare_read_diag.md: -------------------------------------------------------------------------------- 1 | # compare read diag on 160i-W and 31i 2 | 3 | ## read diag value 160i-W 4 | 5 | request: 6 |
  7 | a0 a0 a0 a0 00 01 21 01
  8 | 	00 1e [length]
  9 | 		00 01 [1 subpacket]
 10 | 			00 1c [length subpacket 1]
 11 | 				00 01 00 01 00 30 [Packet Type 01,01,30]
 12 | 				00 00 03 96 [Argument 1 from #918]
 13 | 				00 00 03 96 [Argument 2 to   #918]
 14 | 				00 00 00 01 [Argument 3 first axis]
 15 | 				00 00 00 00 [Argument 4]
 16 | 				00 00 00 00 [Argument 5]
 17 | 
18 | response: 19 |
 20 | a0 a0 a0 a0 00 02 21 02
 21 | 	00 3a [length]
 22 | 		00 01 [1 subpacket]
 23 | 			00 38 [length subpacket 1]
 24 | 				00 01 00 01 00 30 00 00 00 00 00 00 [Packet Type 01,01,30 response OK=0]
 25 | 					00 28 [length payload]
 26 | 						00 00 03 96 00 00 00 02 [#918, axis 0, type double-word]
 27 | 						00 17 72 a3 [1536675]
 28 | 						30 30 32 32 [fill]
 29 | 						20 36 00 00 [fill]
 30 | 						00 00 00 00 [fill]
 31 | 						00 00 00 00 [fill]
 32 | 						00 00 00 00 [fill]
 33 | 						00 00 00 00 [fill]
 34 | 						00 00 00 00 [fill up to MAX_AXIS (8)]
 35 | 
36 | ## read diag value 31i 37 | 38 | request: 39 |
 40 | a0 a0 a0 a0 00 01 21 01
 41 | 	00 1e [length]
 42 | 		00 01 [1 subpacket]
 43 | 			00 1c [length subpacket 1]
 44 | 				00 01 00 01 00 93 [Packet Type 01,01,30]
 45 | 				00 00 01 34 [Argument 1 from #308]
 46 | 				00 00 01 35 [Argument 2 to   #309]
 47 | 				ff ff ff ff [Argument 3 all axes -1]
 48 | 				00 00 00 00 [Argument 4]
 49 | 				00 00 00 00 [Argument 5]
 50 | 
51 | response: 52 |
 53 | a0 a0 a0 a0 00 04 21 02
 54 | 	02 22 [length]
 55 | 		00 01 [1 subpacket]
 56 | 			02 20 [length subpacket 1]
 57 | 				00 01 00 01 00 93 00 00 00 00 00 00 [Packet Type 01,01,93 response OK=0]
 58 | 					02 10 [length payload]
 59 | 						00 00 01 34 ff ff 00 00 [#308, all axes -1]
 60 | 							00 00 00 1c 00 0a 00 00 [value axis 1 = 28]
 61 | 							00 00 00 1c 00 0a 00 00 [value axis 2 = 28]
 62 | 							00 00 00 2c 00 0a 00 00 [value axis 3 = 44]
 63 | 							00 00 00 1a 00 0a 00 00 [value axis 4 = 26]
 64 | 							00 00 00 00 00 0a 00 00 [fill]
 65 | 							00 00 00 00 00 0a 00 00 [fill]
 66 | 							00 00 00 00 00 0a 00 00 [fill]
 67 | 							00 00 00 00 00 0a 00 00 [fill]
 68 | 							00 00 00 00 00 0a 00 00 [fill]
 69 | 							00 00 00 00 00 0a 00 00 [fill]
 70 | 							00 00 00 00 00 0a 00 00 [fill]
 71 | 							00 00 00 00 00 0a 00 00 [fill]
 72 | 							00 00 00 00 00 0a 00 00 [fill]
 73 | 							00 00 00 00 00 0a 00 00 [fill]
 74 | 							00 00 00 00 00 0a 00 00 [fill]
 75 | 							00 00 00 00 00 0a 00 00 [fill]
 76 | 							00 00 00 00 00 0a 00 00 [fill]
 77 | 							00 00 00 00 00 0a 00 00 [fill]
 78 | 							00 00 00 00 00 0a 00 00 [fill]
 79 | 							00 00 00 00 00 0a 00 00 [fill]
 80 | 							00 00 00 00 00 0a 00 00 [fill]
 81 | 							00 00 00 00 00 0a 00 00 [fill]
 82 | 							00 00 00 00 00 0a 00 00 [fill]
 83 | 							00 00 00 00 00 0a 00 00 [fill]
 84 | 							00 00 00 00 00 0a 00 00 [fill]
 85 | 							00 00 00 00 00 0a 00 00 [fill]
 86 | 							00 00 00 00 00 0a 00 00 [fill]
 87 | 							00 00 00 00 00 0a 00 00 [fill]
 88 | 							00 00 00 00 00 0a 00 00 [fill]
 89 | 							00 00 00 00 00 0a 00 00 [fill]
 90 | 							00 00 00 00 00 0a 00 00 [fill]
 91 | 							00 00 00 00 00 0a 00 00 [fill up to MAX_AXIS (32)]
 92 | 						00 00 01 35 ff ff 00 00 [#309, all axes -1]
 93 | 							00 00 00 24 00 0a 00 00 [value axis 1 = 36]
 94 | 							00 00 00 24 00 0a 00 00 [value axis 2 = 36]
 95 | 							00 00 00 31 00 0a 00 00 [value axis 3 = 49]
 96 | 							00 00 00 00 00 0a 00 00 [value axis 4 = 0]
 97 | 							00 00 00 00 00 0a 00 00 [fill]
 98 | 							00 00 00 00 00 0a 00 00 [fill]
 99 | 							00 00 00 00 00 0a 00 00 [fill]
100 | 							00 00 00 00 00 0a 00 00 [fill]
101 | 							00 00 00 00 00 0a 00 00 [fill]
102 | 							00 00 00 00 00 0a 00 00 [fill]
103 | 							00 00 00 00 00 0a 00 00 [fill]
104 | 							00 00 00 00 00 0a 00 00 [fill]
105 | 							00 00 00 00 00 0a 00 00 [fill]
106 | 							00 00 00 00 00 0a 00 00 [fill]
107 | 							00 00 00 00 00 0a 00 00 [fill]
108 | 							00 00 00 00 00 0a 00 00 [fill]
109 | 							00 00 00 00 00 0a 00 00 [fill]
110 | 							00 00 00 00 00 0a 00 00 [fill]
111 | 							00 00 00 00 00 0a 00 00 [fill]
112 | 							00 00 00 00 00 0a 00 00 [fill]
113 | 							00 00 00 00 00 0a 00 00 [fill]
114 | 							00 00 00 00 00 0a 00 00 [fill]
115 | 							00 00 00 00 00 0a 00 00 [fill]
116 | 							00 00 00 00 00 0a 00 00 [fill]
117 | 							00 00 00 00 00 0a 00 00 [fill]
118 | 							00 00 00 00 00 0a 00 00 [fill]
119 | 							00 00 00 00 00 0a 00 00 [fill]
120 | 							00 00 00 00 00 0a 00 00 [fill]
121 | 							00 00 00 00 00 0a 00 00 [fill]
122 | 							00 00 00 00 00 0a 00 00 [fill]
123 | 							00 00 00 00 00 0a 00 00 [fill]
124 | 							00 00 00 00 00 0a 00 00 [fill up to MAX_AXIS (32)]
125 | 
126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyfanuc 2 | focas fanuc protocol-analysis to python-source 3 | 4 | [samplescreens on raspberry and android](#samples) 5 | 6 | The python-source is based on protocol analysis. 7 | The problem is, that the Fanuc Focas Library does not have proper linux support. 8 | The current target platform for protocol-analysis is an EDM-machine with a 160 control and a Robodrill 30i. 9 | 10 | "I need more generated protocols (wireshark) from another fanuc-machines." 11 | 12 | ## implemented 13 | |function|description| 14 | |:------|:---------| 15 | | getsysinfo | read sysinfos | 16 | | readparam | read parameter(s) | 17 | | readdiag | read diagnostic-value(s) | 18 | | readmacro | read macro-value(s) | 19 | | readpmc | read pmc-variables | 20 | | readexecprog | execute linecode | 21 | | readprognum | actual main/run program | 22 | | readalarm | read alarm bitfield | 23 | | readalarmcode | read alarm code/msg | 24 | | settime | set date/time | 25 | | listprog | listprograms | 26 | | getprog | program read test (experimental) | 27 | | readactfeed | actual feedrate | 28 | | readactspindlespeed | actual spindlespeed | 29 | | readaxis | actual axis-values | 30 | | getdate | read date | 31 | | gettime | read time | 32 | | getdatetime | read date+time | 33 | 34 | ### control >= 30i 35 | |function|description| 36 | |:------|:---------| 37 | | readdir_current | current directory | 38 | | readdir_info | directory-info | 39 | | readdir | read directory (one block) | 40 | | readdir_complete | read complete directory | 41 | | readprogname | read mainprogname with path | 42 | 43 | ### subfunctions 44 | |function|description| 45 | |:------|:---------| 46 | | connect | connecting | 47 | | disconnect | disconnecting | 48 | | _req_rdsingle | capsulate single packet request | 49 | | _req_rdmulti | capsulate single packets request | 50 | | _req_rdsub | sub-packet-pack | 51 | | encap | encapsulate packets | 52 | | decap | decapsulate packets | 53 | | _decode8 | decode 8 byte values | 54 | 55 | ## Protocol samples 56 | 57 | ### GETPMC VALUE D2204 58 | #### Request 59 | Header 60 | | Sync | Version | Request | Request length | Subpacket count | 61 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 62 | | A0 A0 A0 A0 | 00 01 | 21 01 | 00 1e | 00 01 | 63 | 64 | Subpacket 1 (length=length+2) 65 | | Length | CNC/PMC | Func | int32 | int32 | int32 | int32 | int32 | 66 | |:------:|:---------:|:---------:|:-----------:|:---------:|:---------:|:---------:|:---------:| 67 | | 00 1c | 00 02 |00 01 80 01| 00 00 08 9c |00 00 08 9d|00 00 00 09|00 00 00 01|00 00 00 00| 68 | | | CNC=1/PMC=2 | | 2204 | 2205 | Memory Type (D) | Type (short) | flll | 69 | 70 | Data Type 71 | | Typ | Description | 72 | |:-----------:|:-------| 73 | | 0 | byte | 74 | | 1 | short | 75 | | 2 | int32 | 76 | 77 | Memory Type 78 | | Typ | | Description | 79 | |:-----------:|:-------:|:-------| 80 | | 0 | G | uplink PMC to CNC | 81 | | 1 | F | downlink PMC from CNC | 82 | | 2 | Y | uplink PMC to Machine | 83 | | 3 | X | downlink PMC from Machine | 84 | | 4 | A | message | 85 | | 5 | R | internal Relays | 86 | | 6 | T | Timer | 87 | | 7 | K | Keep relays | 88 | | 8 | C | Counter | 89 | | 9 | D | Data | 90 | 91 | #### Response 92 | Header 93 | | Sync | Version | Response| Response length| Subpacket count | 94 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 95 | | A0 A0 A0 A0 | 00 02 | 21 02 | 00 14 | 00 01 | 96 | 97 | Subpacket 1 98 | | Length | CNC/PMC | Func | fill | Length payload | int16 | 99 | |:------:|:---------:|:---------:|:------:|:------:|:-----:| 100 | | 00 12 | 00 02 |00 01 80 01| 6 x 00 | 00 02 | 02 58 | 101 | | | CNC=1/PMC=2 | | | 2 | 600 | 102 | 103 | ### GETTIMEDATE Date 14.05.2020 104 | #### Request 105 | Header 106 | | Sync | Version | Request | Request length | Subpacket count | 107 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 108 | | A0 A0 A0 A0 | 00 01 | 21 01 | 00 1e | 00 01 | 109 | 110 | Subpacket 1 (length=length+2) 111 | | Length | CNC/PMC | Func | int32 | int32 | int32 | int32 | int32 | 112 | |:------:|:---------:|:---------:|:-----------:|:---------:|:---------:|:---------:|:---------:| 113 | | 00 1c | 00 01 |00 01 00 45| 00 00 00 00 |00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| 114 | | | CNC=1/PMC=2 | | DATE=0/TIME=1 | | | | | 115 | 116 | #### Response 117 | Header 118 | | Sync | Version | Response| Response length| Subpacket count | 119 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 120 | | A0 A0 A0 A0 | 00 02 | 21 02 | 00 1e | 00 01 | 121 | 122 | Subpacket 1 123 | | Length | CNC/PMC | Func | fill | Length payload | int16 | int16 | int16 | fill | 124 | |:------:|:---------:|:---------:|:------:|:------:|:-----:|:-----:|:-----:|:-------:| 125 | | 00 1c | 00 01 |00 01 00 45| 6 x 00 | 00 0c | e4 07 | 05 00 | 0e 00 | 6 x XX | 126 | | | CNC=1/PMC=2 | | | 12 | 2020 | 5 | 14 | | 127 | 128 | ### GETTIMEDATE Time 12:15:05 129 | #### Request 130 | Header 131 | | Sync | Version | Request | Request length | Subpacket count | 132 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 133 | | A0 A0 A0 A0 | 00 01 | 21 01 | 00 1e | 00 01 | 134 | 135 | Subpacket 1 (length=length+2) 136 | | Length | CNC/PMC | Func | int32 | int32 | int32 | int32 | int32 | 137 | |:------:|:---------:|:---------:|:-----------:|:---------:|:---------:|:---------:|:---------:| 138 | | 00 1c | 00 01 |00 01 00 45| 00 00 00 01 |00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| 139 | | | CNC=1/PMC=2 | | DATE=0/TIME=1 | | | | | 140 | 141 | #### Response 142 | Header 143 | | Sync | Version | Response| Response length| Subpacket count | 144 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 145 | | A0 A0 A0 A0 | 00 02 | 21 02 | 00 1e | 00 01 | 146 | 147 | Subpacket 1 148 | | Length | CNC/PMC | Func | fill | Length payload | fill | int16 | int16 | int16 | 149 | |:------:|:---------:|:---------:|:------:|:------:|:-----:|:-----:|:-----:|:-------:| 150 | | 00 1c | 00 01 |00 01 00 45| 6 x 00 | 00 0c | 6 x XX | 00 0c | 00 0f | 00 05 | 151 | | | CNC=1/PMC=2 | | | 12 | | 12 | 15 | 5 | 152 | 153 | 154 | ### GETDIAG 980-981 for first Axis 155 | #### Request 156 | Header 157 | | Sync | Version | Request | Request length | Subpacket count | 158 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 159 | | A0 A0 A0 A0 | 00 01 | 21 01 | 00 1e | 00 01 | 160 | 161 | Subpacket 1 162 | | Length | CNC/PMC | Func | int32 | int32 | int32 | int32 | int32 | 163 | |:------:|:---------:|:---------:|:-----------:|:---------:|:---------:|:---------:|:---------:| 164 | | 00 1c | 00 01 |00 01 00 30| 00 00 03 d4 |00 00 03 d5|00 00 00 01|00 00 00 00|00 00 00 00| 165 | | | CNC=1/PMC=2 | | 980 | 981 | Axis 1 | | | 166 | 167 | #### Response 168 | Header 169 | | Sync | Version |Response |Response length | Subpacket count | 170 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 171 | | A0 A0 A0 A0 | 00 02 | 21 02 | 00 62 | 00 01 | 172 | 173 | Subpacket 1 (length=length+2) 174 | | Length | CNC/PMC | Func | fill | Length payload | 175 | |:------:|:---------:|:---------:|:------:|:------:| 176 | | 00 60 | 00 01 |00 01 00 30| 6 x 00 | 00 50 | 177 | | | CNC=1/PMC=2 | | | 2x(4+2+2+MAX_AXISx4)=80 | 178 | 179 | Diag-Value 980 [MAX_AXIS=8 Values] 180 | | Name | Axis | Datatype | int32 | 7 x int32 | 181 | |:-----------:|:-----:|:---------:|:-----------:|:---------------:| 182 | | 00 00 03 d4 | 00 01 | 00 02 | ff f6 de aa | 7 x 00 00 00 00 | 183 | | 980 | 1 | 2-word | ‭-598.358‬ | | 184 | 185 | Diag-Value 981 [MAX_AXIS=8 Values] 186 | | Name | Axis | Datatype | int32 | 7 x int32 | 187 | |:-----------:|:-----:|:---------:|:-----------:|:---------------:| 188 | | 00 00 03 d5 | 00 01 | 00 02 | ff e2 62 6c | 7 x 00 00 00 00 | 189 | | 981 | 1 | 2-word | ‭-1.940.884 | | 190 | 191 | 192 | ## Programmtransfer 193 | 194 | getprog(self,name) ist the test-implementation for programm-transfer. 195 | 196 | programtransfer-stream connects with a0 a0 a0 a0 00 01 01 01 00 02 00 01 197 | 198 | controltransfer-stream (params etc.) connects with a0 a0 a0 a0 00 01 01 01 00 02 00 02 199 | 200 | Start Transfer 201 | | Sync | Version | Request | Request length | unknown | zeroterm. Prognames | 202 | |:-----------:|:-------:|:-------:|:-------:|:---------:|:---------:| 203 | | A0 A0 A0 A0 | 00 01 | 15 01 | 02 04 | 00 00 00 01 | "O2200-O2200" 00 .. | 204 | 205 | 206 | | Sync | Version | Response| Response length| unknown | 207 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 208 | | A0 A0 A0 A0 | 00 02 | 15 02 | 02 01 | .. | 209 | 210 | # if not exist 211 | Receive block 212 | | Sync | Version | Response| Response length| 213 | |:-----------:|:-------:|:-------:|:-------:| 214 | | A0 A0 A0 A0 | 00 02 | 16 04 | 00 00 | 215 | 216 | # if exist 217 | Receive block 218 | | Sync | Version | Response| Response length| Programtext | 219 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 220 | | A0 A0 A0 A0 | 00 02 | 16 04 | 05 00 | .. | 221 | 222 | Receive block 223 | | Sync | Version | Response| Response length| Programtext | 224 | |:-----------:|:-------:|:-------:|:-------:|:---------:| 225 | | A0 A0 A0 A0 | 00 02 | 16 04 | 05 00 | ... "%" | 226 | 227 | Transfer end 228 | | Sync | Version | Response| Response length| 229 | |:-----------:|:-------:|:-------:|:-------:| 230 | | A0 A0 A0 A0 | 00 02 | 17 01 | 00 00 | 231 | 232 | Stop Transfer 233 | | Sync | Version | Request | Request length | 234 | |:-----------:|:-------:|:-------:|:-------:| 235 | | A0 A0 A0 A0 | 00 01 | 17 02 | 00 00 | 236 | 237 | # samples 238 | 239 | ## sample on raspberry pi 2 only with python3 and without x86-emu/wine etc. 240 | 241 | ![Test Image](/images/test.png) 242 | 243 | ## sample on Samsung A51 with Pydroid-Android 244 | 245 | import pyfanuc 246 | conn=pyfanuc('192.168.0.61') 247 | if conn.connect(): 248 | print("connected") 249 | print('type:'+conn.sysinfo['cnctype'].decode()) 250 | print(conn.getdatetime()) 251 | print(conn.statinfo()) 252 | if conn.disconnect(): 253 | print("disconnected") 254 | 255 | ![Test Image](/images/Pydroid_3_Screenshot_A51.png) 256 | 257 | -------------------------------------------------------------------------------- /pyfanuc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import socket,time,datetime 3 | from struct import pack,unpack 4 | 5 | class pyfanuc(object): 6 | def __init__(self, ip, port=8193): 7 | self.sock=None 8 | self.ip=ip 9 | self.port=port 10 | self.connected=False 11 | FTYPE_OPN_REQU=0x0101;FTYPE_OPN_RESP=0x0102 12 | FTYPE_VAR_REQU=0x2101;FTYPE_VAR_RESP=0x2102 13 | FTYPE_CLS_REQU=0x0201;FTYPE_CLS_RESP=0x0202 14 | FRAME_SRC=b'\x00\x01' 15 | FRAME_DST=b'\x00\x02';FRAME_DST2=b'\x00\x01' 16 | FRAMEHEAD=b'\xa0\xa0\xa0\xa0' 17 | def connect(self): 18 | "Establish connection to machine and set parameters with sysinfo" 19 | # try: 20 | self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 21 | self.sock.settimeout(5) 22 | self.sock.connect((self.ip,self.port)) 23 | self.sock.settimeout(1) 24 | self.sock.sendall(self._encap(pyfanuc.FTYPE_OPN_REQU,pyfanuc.FRAME_DST)) 25 | data=self._decap(self.sock.recv(1500)) 26 | if data["ftype"]==pyfanuc.FTYPE_OPN_RESP: 27 | self.connected=True 28 | self.getsysinfo() 29 | # except: 30 | # print("ERROR") 31 | # self.sock=None 32 | # self.connected=False 33 | return self.connected 34 | def disconnect(self): 35 | "Disconnect the connection to the machine" 36 | if self.connected: 37 | self.sock.sendall(self._encap(pyfanuc.FTYPE_CLS_REQU,b'')) 38 | data=self._decap(self.sock.recv(1500)) 39 | if data["ftype"]==pyfanuc.FTYPE_CLS_RESP: 40 | return True 41 | return False 42 | 43 | def _encap(self,ftype,payload,fvers=1): 44 | "intern function - Encapsulate packetdata" 45 | if ftype==pyfanuc.FTYPE_VAR_REQU: 46 | pre=[] 47 | if isinstance(payload,list): 48 | for t in payload: 49 | pre.append(pack(">H",len(t)+2)+t) 50 | payload=pack(">H",len(pre))+b''.join(pre) 51 | else: 52 | payload=pack(">HH",1,len(payload)+2)+payload 53 | return pyfanuc.FRAMEHEAD+pack(">HHH",fvers,ftype,len(payload))+payload 54 | def _decap(self,data): 55 | "intern function - Decapsulate packetdata" 56 | if len(data)<10: 57 | return {"len":-1} 58 | if not data.startswith(b'\xa0'*4): 59 | return {"len":-1} 60 | fvers,ftype,len1=unpack(">HHH",data[4:10]) 61 | if len1+10 != len(data): 62 | return {"len":-1} 63 | if len1==0: 64 | return {"len":0,"ftype":ftype,"fvers":fvers,"data":b'0'} 65 | data=data[10:] 66 | if ftype==pyfanuc.FTYPE_VAR_RESP: 67 | re=[] 68 | qu=unpack(">H",data[0:2])[0] 69 | n=2 70 | for t in range(qu): 71 | le=unpack(">H",data[n:n+2])[0] 72 | re.append(data[n+2:n+le]) 73 | n+=le 74 | return {"len":len1,"ftype":ftype,"fvers":fvers,"data":re} 75 | else: # ftype==FTYPE_OPN_RESP or ftype==FTYPE_CLS_RESP 76 | return {"len":len1,"ftype":ftype,"fvers":fvers,"data":data} 77 | def _req_rdsingle(self,c1,c2,c3,v1=0,v2=0,v3=0,v4=0,v5=0,pl=b""): 78 | "intern function - pack simple command" 79 | cmd=pack(">HHH",c1,c2,c3) 80 | self.sock.sendall(self._encap(pyfanuc.FTYPE_VAR_REQU,cmd+pack(">iiiii",v1,v2,v3,v4,v5)+pl)) 81 | t=self._decap(self.sock.recv(1500)) 82 | if t["len"]==0: 83 | return {"len":-1} 84 | elif t["ftype"]!=pyfanuc.FTYPE_VAR_RESP: 85 | return {"len":-1} 86 | elif t["data"][0].startswith(cmd+b'\x00'*6): 87 | return {"len":unpack(">H",t["data"][0][12:14])[0],"data":t["data"][0][14:]} 88 | elif t["data"][0].startswith(cmd): 89 | return {"len":0,"data":t["data"][0][6:],"error":unpack(">h",t["data"][0][6:8])[0]} 90 | else: 91 | return {"len":-1} 92 | def _req_rdmulti(self,l): 93 | "intern function - pack multiple commands" 94 | self.sock.sendall(self._encap(pyfanuc.FTYPE_VAR_REQU,l)) 95 | t=self._decap(self.sock.recv(1500)) 96 | if t["len"]==0: 97 | return {"len":-1} 98 | elif t["ftype"]!=pyfanuc.FTYPE_VAR_RESP: 99 | return {"len":-1} 100 | if len(l) != len(t["data"]): 101 | return {"len":-1} 102 | for x in range(len(t["data"])): 103 | if t["data"][x][0:6] == l[x][0:6]: 104 | if t["data"][x][6:12]==b'\x00'*6: 105 | t["data"][x]=[0,t["data"][x][12:]] 106 | else: 107 | t["data"][x]=[unpack('>h',t["data"][x][0:2])[0],t["data"][x][12:]] 108 | else: 109 | return {"len":-1} 110 | return t 111 | def _req_rdsub(self,c1,c2,c3,v1=0,v2=0,v3=0,v4=0,v5=0): 112 | "intern function - pack subfunction info" 113 | return pack(">HHHiiiii",c1,c2,c3,v1,v2,v3,v4,v5) 114 | def _decode8(self,val): 115 | "intern function - decode value from 8 bytes" 116 | if val[5]==2 or val[5]==10: 117 | if val[-2:]==b'\xff'*2: 118 | return None 119 | else: 120 | return unpack(">i",val[0:4])[0]/val[5]**val[7] 121 | def statinfo(self): 122 | """ 123 | Get state of machine 124 | """ 125 | st=self._req_rdsingle(1,1,0x19,0) 126 | if (self.sysinfo["cnctype"]==b"16" or self.sysinfo["cnctype"]==b"31") and st["len"]==0xe: 127 | return dict(zip(['aut','run','motion','mstb','emegency','alarm','edit'], 128 | unpack(">HHHHHHH",st["data"]))) 129 | def getdate(self): 130 | """ 131 | Get date 132 | returns [YEAR,MONTH,DAY] 133 | """ 134 | st=self._req_rdsingle(1,1,0x45,0) 135 | if st["len"]==0xc: 136 | return unpack(">HHH",st["data"][0:6]) 137 | def gettime(self): 138 | """ 139 | Get time 140 | returns [HOUR,MINUTE,SECOND] 141 | """ 142 | st=self._req_rdsingle(1,1,0x45,1) 143 | if st["len"]==0xc: 144 | return unpack(">HHH",st["data"][-6:]) 145 | def getdatetime(self): 146 | """ 147 | Get date and time 148 | returns time.struct_time 149 | """ 150 | st=self._req_rdmulti([self._req_rdsub(1,1,0x45,0),self._req_rdsub(1,1,0x45,1)]) 151 | if st["len"]<0: 152 | return 153 | if len(st["data"]) != 2: 154 | return 155 | if st["data"][0][0]!=0 or st["data"][1][0]!=0: 156 | return 157 | if unpack(">H",st["data"][0][1][0:2])[0] == 0xc and unpack(">H",st["data"][1][1][0:2])[0] == 0xc: 158 | return datetime.datetime(*unpack(">HHHHHH",st["data"][0][1][2:8]+st["data"][1][1][-6:])).timetuple() 159 | def getsysinfo(self): 160 | """ 161 | Get sysinfo 162 | returns ['addinfo','maxaxis','cnctype','mttype','series','version','axes'] 163 | """ 164 | st=self._req_rdsingle(1,1,0x18) 165 | if st["len"]==0x12: 166 | self.sysinfo=dict(zip(['addinfo','maxaxis','cnctype','mttype','series','version','axes'], 167 | unpack(">HH2s2s4s4s2s",st["data"]))) 168 | 169 | FORMAT_AXIS,FORMAT_TOOLOFF,FORMAT_MACRO,FORMAT_WORKZOFF,FORMAT_CUTFR=0,1,2,3,4; 170 | def getformat(self,type=0): 171 | "get typespecific numberformat" 172 | st=self._req_rdsingle(1,1,0x1b,type) 173 | if st["len"]>=4+2*2: 174 | n={'type':type,'count':unpack(">i",st["data"][0:4])[0]} 175 | t=[] 176 | for x in range(4,st["len"],4): 177 | t.append(dict(zip(['decinput','decoutput'],unpack(">HH",st["data"][x:x+4])))) 178 | if len(t)>1: 179 | n["dec"]=t 180 | else: 181 | n.update(t[0]) 182 | return n 183 | 184 | ABS=1;REL=2;REF=4;SKIP=8;DIST=16 185 | ALLAXIS=-1 186 | def readaxes(self,what=1,axis=ALLAXIS): 187 | r=[] 188 | axvalues=(("ABS",pyfanuc.ABS,4),("REL",pyfanuc.REL,6),("REF",pyfanuc.REF,1),("SKIP",pyfanuc.SKIP,8),("DIST",pyfanuc.DIST,7)) 189 | for u,v,w in axvalues: 190 | if what & v: 191 | r.append(self._req_rdsub(1,1,0x26,w,axis)) 192 | st=self._req_rdmulti(r) 193 | if st["len"]<0: 194 | return 195 | r={} 196 | for x in st["data"]: 197 | ret1=[] 198 | if x[0]!=0: 199 | ret1=None 200 | else: 201 | for pos in range(2,unpack(">H",x[1][0:2])[0]+2,8): 202 | value=x[1][pos:pos+8] 203 | ret1.append(self._decode8(value)) 204 | for u,v,w in axvalues: 205 | if what & v: 206 | r[u]=ret1 207 | what &= ~v 208 | break 209 | return r 210 | def readparam(self,axis,first,last=0): 211 | if last==0:last=first 212 | st=self._req_rdsingle(1,1,0x0e,first,last,axis) 213 | if st["len"]<0: 214 | return 215 | r={} 216 | for pos in range(0,st["len"],self.sysinfo["maxaxis"]*4+8): 217 | varname,axiscount,valtype=unpack(">IhH",st["data"][pos:pos+8]) 218 | values={"type":valtype,"axis":axiscount,"data":[]} 219 | for n in range(pos+8,pos+self.sysinfo["maxaxis"]*4+8,4): 220 | value=st["data"][n:n+4] 221 | if valtype==0: 222 | value=value[-1] #bit 1bit / Byte 223 | elif valtype==1: 224 | value=[(value[-1] >> n)& 1 for n in range(7,-1,-1)] #bit 8bit 225 | elif valtype==2: 226 | value=unpack(">h",value[-2])[0] #short 227 | elif valtype==3: 228 | value=unpack(">i",value)[0] #int 229 | if axiscount != -1: 230 | values["data"].append(value) 231 | break 232 | else: 233 | values["data"].append(value) 234 | r[varname]=values 235 | return r 236 | def readdiag(self,axis,first,last=0): 237 | if last==0:last=first 238 | st=self._req_rdsingle(1,1,0x30,first,last,axis) 239 | if st["len"]<0: 240 | return 241 | r={} 242 | for pos in range(0,st["len"],self.sysinfo["maxaxis"]*4+8): 243 | varname,axiscount,valtype=unpack(">IhH",st["data"][pos:pos+8]) 244 | values={"type":valtype,"axis":axiscount,"data":[]} 245 | for n in range(pos+8,pos+self.sysinfo["maxaxis"]*4+8,4): 246 | value=st["data"][n:n+4] 247 | if valtype==4 or valtype==0: 248 | value=value[-1] #bit 1bit / Byte 249 | elif valtype==1: 250 | value=unpack(">h",value[-2])[0] #short 251 | elif valtype==2: 252 | value=unpack(">i",value)[0] #int 253 | elif valtype==3: 254 | value=[(value[-1] >> n)& 1 for n in range(7,-1,-1)] #bit 8bit 255 | if axiscount != -1: 256 | values["data"].append(value) 257 | break 258 | else: 259 | values["data"].append(value) 260 | r[varname]=values 261 | return r 262 | def readmacro(self,first,last=0): 263 | if last==0: last=first 264 | st=self._req_rdsingle(1,1,0x15,first,last) 265 | if st["len"]<=0: 266 | return 267 | r={} 268 | for pos in range(0,st["len"],8): 269 | r[first]=self._decode8(st["data"][pos:pos+8]) 270 | first+=1 271 | return r 272 | def readpmc(self,datatype,section,first,count=1): 273 | last=first+(1<>datatype): 279 | pos=(1<H",st["data"][pos:pos+2])[0] 284 | elif datatype==2: 285 | value=unpack(">I",st["data"][pos:pos+4])[0] 286 | r[first+(1<i",st["data"][0:4])[0],"text":st["data"][4:].decode()} 293 | def readprognum(self): 294 | """ 295 | Get the running program and main program numbers 296 | returns [running,main] 297 | """ 298 | st=self._req_rdsingle(1,1,0x1c) 299 | if st["len"]<8: 300 | return 301 | return {"run":unpack(">i",st["data"][0:4])[0],"main":unpack(">i",st["data"][4:])[0]} 302 | def readprogname(self): #31i 303 | """ 304 | Get current mainprogname 305 | returns name with path 306 | """ 307 | st=self._req_rdsingle(1,1,0xb9) 308 | if st["len"]>=0: 309 | p=st["data"].split(b'\0', 1)[0] 310 | return p.decode() 311 | return None 312 | def settime(self,h=-1,m=0,s=0): 313 | """ 314 | Set Time to Parameter-Values or actual PC-Time 315 | variant 1 - requests nothing for actual PC-Time to set 316 | variant 2 - requests hour,optional minute (default 0),optional second (default 0) 317 | """ 318 | if h==-1: 319 | t=time.localtime() 320 | h,m,s=t.tm_hour,t.tm_min,t.tm_sec 321 | self.sock.sendall(self._encap(pyfanuc.FTYPE_VAR_REQU,self._req_rdsub(1,1,0x46,1,0,0,0,12)+b'\x00'*6+pack(">HHH",h,m,s))) 322 | t=self._decap(self.sock.recv(1500)) 323 | if t["len"]==18: 324 | if t["ftype"]==pyfanuc.FTYPE_VAR_RESP and unpack(">HHH",t["data"][0][0:6])==(1,1,0x46): 325 | return unpack(">h",t["data"][0][6:8])[0] 326 | def listprog(self,start=1): 327 | ret={} 328 | while True: 329 | st=self._req_rdsingle(1,1,0x06,start,0x13,2) 330 | if st["len"] < -1: 331 | return None 332 | elif st["len"]==0: 333 | return ret 334 | for t in range(0,st["len"],72): 335 | number,size,comment=unpack(">II64s",st["data"][t:t+72]) 336 | comment=comment.split(b'\0', 1)[0] 337 | start=number+1 338 | ret[number]={"size":size,"comment":comment.decode()} 339 | def readalarm(self): 340 | "Read alarm Bitfield" 341 | st=self._req_rdsingle(1,1,0x1a) 342 | if st["len"]==4: 343 | return unpack(">L",st["data"])[0] 344 | return None 345 | def readalarmcode(self,type,withtext=0,maxmsgs=-1,textlength=32): 346 | "Read alarm code / msg" 347 | #readalarmmsg Returns Alarmcode+Msgtext 1,1,0x23,int32 Type,int32 MaxMsgs,int32 0 w/o or 1/2 with text,int32 MaxTextLength 348 | # int32 AlarmCode,int32 AlarmType,int32 Axis,int32 TextLength,text/trash 349 | if maxmsgs<=0: 350 | maxmsgs=int(self.sysinfo['axes']) 351 | st=self._req_rdsingle(1,1,0x23,type,maxmsgs,withtext,textlength) 352 | ret=[] 353 | if st["len"] > 0: 354 | for pos in range(0,st["len"],4*4+textlength): 355 | entry=dict(zip(['alarmcode','alarmtype','axis'],unpack(">iii",st["data"][pos:pos+4*3]))) 356 | txlen=unpack(">i",st["data"][pos+4*3:pos+4*4])[0] 357 | if txlen>0 and withtext>0: 358 | entry["text"]=st["data"][pos+4*4:pos+4*4+textlength] 359 | ret.append(entry) 360 | return ret 361 | return None 362 | def readdir_current(self,fgbg=1): #31i 363 | """ 364 | Get current directory 365 | requests 1 (default) for foreground or 2 for background 366 | returns directoryname 367 | """ 368 | st=self._req_rdsingle(1,1,0xb0,fgbg) 369 | if st["len"]>=0: 370 | p=st["data"].split(b'\0', 1)[0] 371 | return p.decode() 372 | return None 373 | def readdir_info(self,dir): #31i 374 | buffer=bytearray(0x100) 375 | bdir=dir.encode() 376 | buffer[0:len(bdir)]=bdir 377 | st=self._req_rdsingle(1,1,0xb4,0,0,0,0,256,buffer) 378 | if st["len"]>=8: 379 | return dict(zip(['dirs','files'],unpack(">ii",st["data"]))) 380 | return None 381 | def readdir(self,dir,first=0,count=10,type=0,size=1): #30i 382 | buffer=bytearray(0x100) 383 | bdir=dir.encode() 384 | buffer[0:len(bdir)]=bdir 385 | st=self._req_rdsingle(1,1,0xb3,first,count,type,size,256,buffer) 386 | x=[] 387 | if st["len"]>=8: 388 | for t in range(0,st["len"],128): 389 | n=dict(zip(['type','datetime','unkn','size','attr','name','comment','proctimestamp'],unpack(">h12s6sII36s52s12s",st["data"][t:t+128]))) 390 | del n['unkn'] 391 | if n['type']==1: 392 | n['comment']=n['comment'].split(b'\0', 1)[0].decode() 393 | n['datetime']=datetime.datetime(*unpack(">HHHHHH",n['datetime'])).timetuple() 394 | else: 395 | n['comment']=None 396 | n['size']=None 397 | n['datetime']=None 398 | n['name']=n['name'].split(b'\0', 1)[0].decode() 399 | n['type']='D' if n['type']==0 else 'F' 400 | x.append(n) 401 | return(x) 402 | return None 403 | def readdir_complete(self,dir): #30i 404 | t=self.readdir_info(dir) 405 | n=t['dirs']+t['files'] 406 | ret=[] 407 | for t in range(0,n,10): 408 | x=self.readdir(dir,first=t,count=10) 409 | if not x is None: 410 | ret.extend(x) 411 | else: 412 | break 413 | return ret 414 | def getprog(self,name): #TEST Stream 415 | """ 416 | Get program-file 417 | requests filename 418 | returns filecontent 419 | """ 420 | q=b'' 421 | if isinstance(name,int): 422 | q=("O%04i-O%04i" % (name,name)).encode() 423 | elif isinstance(name,str): 424 | name=name.upper() 425 | if not name.startswith("O"): 426 | name="O"+name 427 | if name.find("-")==-1: 428 | name=name+"-"+name 429 | q=name.encode() 430 | else: 431 | return -1 432 | buffer=bytearray(0x204) 433 | self.sock2=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 434 | self.sock2.connect((self.ip,self.port)) 435 | self.sock2.settimeout(1) 436 | self.sock2.sendall(self._encap(pyfanuc.FTYPE_OPN_REQU,pyfanuc.FRAME_DST2)) 437 | data=self._decap(self.sock2.recv(1500)) 438 | buffer[0:4]=b'\x00\x00\x00\x01' 439 | buffer[4:4+len(q)]=q #buffer[4:15]=b'\x4f\x30\x31\x30\x30\x2d\x4f\x30\x31\x30\x30' 440 | self.sock2.sendall(self._encap(0x1501,buffer)) 441 | data=self._decap(self.sock2.recv(1500)) 442 | #print(data) 443 | f=b'' 444 | n=b'' 445 | while True: 446 | n+=self.sock2.recv(1500) 447 | while len(n)>=10: 448 | if n[:4]==pyfanuc.FRAMEHEAD: 449 | fvers,ftype,flen=unpack(">HHH",n[4:10]) 450 | if len(n)') 485 | print(conn.getdatetime()) 486 | #print(conn.readaxes(pyfanuc.ABS | pyfanuc.DIST)) 487 | #print(conn._req_rdsingle(1,1,0x8a)) 488 | if conn.disconnect(): 489 | print("disconnected") 490 | 491 | # conn=pyfanuc('192.168.0.61') 492 | # if conn.connect(): 493 | # print("connected") 494 | # print(conn.sysinfo) 495 | # print(conn.readactfeed()) 496 | # if conn.disconnect(): 497 | # print("disconnected") 498 | --------------------------------------------------------------------------------