ahio  1.0.0
I/O Communication Library
snap7.py
Go to the documentation of this file.
1 # -*- coding: utf-8; -*-
2 #
3 # Copyright (c) 2016 Álan Crístoffer
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22 
24 
25 from enum import Enum
26 
27 try:
28  import snap7
29 except Exception:
30  ahioDriverInfo.AVAILABLE = False
31 
32 
34  NAME = 'snap7'
35  AVAILABLE = True
36 
37 
39  _client = None
40 
41  def __enter__(self):
42  return self
43 
44  def __exit__(self, exc_type, exc_value, traceback):
45  if self._client:
46  self._client.disconnect()
47  self._client = None
48 
49 
89  def setup(self, address, rack=0, slot=1, port=102):
90  self._client = snap7.client.Client()
91  self._client.connect(address, rack, slot, port)
92 
93  def available_pins(self):
94  return []
95 
96  def _set_pin_direction(self, pin, direction):
97  d = self._pin_direction(pin)
98  if direction != d and not (type(d) is list and direction in d):
99  raise RuntimeError('Port %s does not support this Direction' % pin)
100 
101  def _pin_direction(self, pin):
102  return {
103  'D': [ahio.Direction.Input, ahio.Direction.Output],
104  'M': [ahio.Direction.Input, ahio.Direction.Output],
105  'Q': ahio.Direction.Output,
106  'I': ahio.Direction.Input
107  }[pin[0].upper()]
108 
109  def _set_pin_type(self, pin, ptype):
110  raise RuntimeError('Hardware does not support changing the pin type')
111 
112  def _pin_type(self, pin):
113  raise RuntimeError('Hardware does not support querying the pin type')
114 
115  def _write(self, pin, value, pwm):
116  if pwm:
117  raise RuntimeError('Pin does not support PWM')
118  if self._pin_direction(pin) == ahio.Direction.Input:
119  raise RuntimeError('Can not write to Input')
120  mem = self._parse_port_name(pin)
121  value = {
122  ahio.LogicValue.High: 1,
123  ahio.LogicValue.Low: 0
124  }.get(value, value)
125  self._set_memory(mem, value)
126 
127  def _read(self, pin):
128  mem = self._parse_port_name(pin)
129  value = self._get_memory(mem)
130  if mem[1] == 'X':
131  return {
132  0: ahio.LogicValue.Low,
133  1: ahio.LogicValue.High
134  }.get(value, value)
135  else:
136  return value
137 
138  def analog_references(self):
139  return []
140 
141  def _set_analog_reference(self, reference, pin):
142  raise RuntimeError('Hardware does not support setting analog ref')
143 
144  def _analog_reference(self, pin):
145  pass
146 
147  def _set_pwm_frequency(self, frequency, pin):
148  raise RuntimeError(
149  'Setting PWM frequency is not supported by hardware')
150 
151  def _parse_port_name(self, s):
152  s = s.upper()
153  area = {
154  'D': snap7.snap7types.S7AreaDB,
155  'M': snap7.snap7types.S7AreaMK,
156  'Q': snap7.snap7types.S7AreaPA,
157  'I': snap7.snap7types.S7AreaPE
158  }[s[0]]
159  length = {'X': 1, 'B': 1, 'W': 2, 'D': 4}[s[1]]
160  start = int(s.split('.')[0][2:])
161  bit = int(s.split('.')[1]) if s[1] == 'X' else None
162  dtype = {
163  'X': {
164  'get': lambda m: snap7.util.get_bool(m, 0, bit),
165  'set': lambda m, v: snap7.util.set_bool(m, 0, bit, v)
166  },
167  'B': {
168  'get': lambda m: snap7.util.get_int(m, 0),
169  'set': lambda m, v: snap7.util.set_int(m, 0, v)
170  },
171  'W': {
172  'get': lambda m: snap7.util.get_int(m, 0),
173  'set': lambda m, v: snap7.util.set_int(m, 0, v)
174  },
175  'D': {
176  'get': lambda m: snap7.util.get_dword(m, 0),
177  'set': lambda m, v: snap7.util.set_dword(m, 0, v)
178  }
179  }[s[1]]
180  return (area, dtype, start, length)
181 
182  def _get_memory(self, mem):
183  m = self._client.read_area(mem[0], 0, mem[2], mem[3])
184  return mem[1]['get'](m)
185 
186  def _set_memory(self, mem, value):
187  m = self._client.read_area(mem[0], 0, mem[2], mem[3])
188  mem[1]['set'](m, value)
189  self._client.write_area(mem[0], 0, mem[2], m)
def __exit__(self, exc_type, exc_value, traceback)
Definition: snap7.py:44
def _set_memory(self, mem, value)
Definition: snap7.py:186
def __enter__(self)
Definition: snap7.py:41
def _pin_direction(self, pin)
Definition: snap7.py:101
Abstract class containing information about the driver.
def available_pins(self)
Definition: snap7.py:93
def _get_memory(self, mem)
Definition: snap7.py:182
def analog_references(self)
Definition: snap7.py:138
def _parse_port_name(self, s)
Definition: snap7.py:151
Contains abstract classes that should be implemented by drivers.
def setup(self, address, rack=0, slot=1, port=102)
Connects to a Siemens S7 PLC.
Definition: snap7.py:89