Skip to content

Commit

Permalink
Refactor source code generator for "bodyparts" // Resolve #19
Browse files Browse the repository at this point in the history
  • Loading branch information
ivankravets committed Nov 12, 2015
1 parent f631f1e commit 43bd911
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 30 deletions.
22 changes: 13 additions & 9 deletions smartanthill/cc/platformio.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def _clone_project(self, dir_path):
if isdir(self.project_dir):
rmtree(self.project_dir)
copytree(dir_path, self.project_dir)
if isdir(join(self.project_dir, ".pioenvs")):
rmtree(join(self.project_dir, ".pioenvs"))

def _generate_env_name(self):
data = ["%s_%s" % (k, v) for k, v in self.project_conf.iteritems()]
Expand Down Expand Up @@ -217,15 +219,6 @@ def build_firmware(project_dir, platformio_conf, bodyparts, buses,
zepto_conf = dict(AES_ENCRYPTION_KEY=range(0, 16))

pio = PlatformIOProject(project_dir, platformio_conf)
pio.add_src_content(
"sa_bodypart_list.cpp", srcgen.BodyPartListCPP(bodyparts).generate()
)
pio.add_src_content(
"sa_bus_list.cpp", srcgen.BusListCPP(buses).generate()
)
pio.add_src_content(
"zepto_config.h", srcgen.ZeptoConfigH(zepto_conf).generate()
)

# copy user's plugins
for item in bodyparts:
Expand All @@ -245,6 +238,17 @@ def build_firmware(project_dir, platformio_conf, bodyparts, buses,
join("transports", item.transport.get_id()))
)

# dynamic content
pio.add_src_content(
"sa_bodypart_list.cpp", srcgen.BodyPartListCPP(bodyparts).generate()
)
# pio.add_src_content(
# "sa_bus_list.cpp", srcgen.BusListCPP(buses).generate()
# )
pio.add_src_content(
"zepto_config.h", srcgen.ZeptoConfigH(zepto_conf).generate()
)

return pio.run(
target="build", options={"disable-auto-clean": disable_auto_clean})

Expand Down
100 changes: 82 additions & 18 deletions smartanthill/cc/srcgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import re
from os.path import join
from string import Template


Expand Down Expand Up @@ -41,12 +43,31 @@ class SourceGenerator(object):
*******************************************************************************/
"""

C_STRUCT_RE = re.compile(
r"typedef\s+struct\s+\w+\s*"
"\{\s*([^\}]+)\s*\}\s+(\w+)\s*;", re.M)
C_STRUCT_MEMBER_RE = re.compile(r"(\w+)\s*\*?\s*(\w+)(\[\d+\])?\s*;", re.M)

STRIP_COMMENTS_RE = re.compile(
r"(/\*.*?\*/|\s+//[^\r\n]*$)", re.M | re.S)

def get_content(self):
raise NotImplementedError

def generate(self):
return "%s\n%s" % (self.COPYRIGHT.strip(), self.get_content())

def parse_c_structs(self, path):
content = ""
with open(path) as f:
content = f.read()
content = self.STRIP_COMMENTS_RE.sub("", content)

members = {}
for item in self.C_STRUCT_RE.findall(content):
members[item[1]] = self.C_STRUCT_MEMBER_RE.findall(item[0])
return members


class ZeptoConfigH(SourceGenerator):

Expand All @@ -55,11 +76,11 @@ class ZeptoConfigH(SourceGenerator):
#if !defined __ZEPTO_CONFIG_H__
#define __ZEPTO_CONFIG_H__
#define DECLARE_AES_ENCRYPTION_KEY \
const uint8_t AES_ENCRYPTION_KEY[16] ZEPTO_PROG_CONSTANT_LOCATION = \
{ ${AES_ENCRYPTION_KEY} }; \
#define DECLARE_AES_ENCRYPTION_KEY \\
const uint8_t AES_ENCRYPTION_KEY[16] ZEPTO_PROG_CONSTANT_LOCATION = \\
{ ${AES_ENCRYPTION_KEY} }; \\
#define DECLARE_DEVICE_ID \
#define DECLARE_DEVICE_ID \\
uint16_t DEVICE_SELF_ID = 1;
#endif // __ZEPTO_CONFIG_H__
Expand Down Expand Up @@ -97,6 +118,13 @@ class BodyPartListCPP(SourceGenerator):
def __init__(self, bodyparts):
self.bodyparts = bodyparts

self._c_structs = {}
for bodypart in self.bodyparts:
self._c_structs[bodypart.get_id()] = self.parse_c_structs(
join(bodypart.plugin.get_source_dir(),
"%s.h" % bodypart.plugin.get_id())
)

def get_content(self):
return self.TPL.substitute(
bodypart_nums=len(self.bodyparts),
Expand All @@ -116,28 +144,64 @@ def _gen_plugin_includes(self):
def _gen_plugin_configs(self):
configs = []
for bodypart in self.bodyparts:

data = []
for items in (bodypart.get_peripheral(), bodypart.get_options()):
if not items:
continue
for item in items:
if item['type'].startswith("char["):
data.append('.%s="%s"' % (item['name'], item['value']))
else:
data.append(".%s=%s" % (item['name'], item['value']))

data = self._get_plugin_conf_data(bodypart)
if data['hapi_gpio_vars']:
configs.extend(data['hapi_gpio_vars'])
config = (
"{pid}_plugin_config {pid}_plugin_config_{bpid}"
.format(bpid=bodypart.get_id(),
pid=bodypart.plugin.get_id())
)
if data:
config += "={ %s }" % ", ".join(data)
if data['struct_values']:
config += "={ %s }" % ", ".join(data['struct_values'])
configs.append(config + ";")

return configs

def _get_plugin_conf_data(self, bodypart):
data = {
"hapi_gpio_vars": [],
"struct_values": []
}
c_struct_name = "%s_plugin_config" % bodypart.plugin.get_id()
bodypart_id = bodypart.get_id()
c_structs = self._c_structs[bodypart_id]
assert c_struct_name in c_structs

for s_item in c_structs[c_struct_name]:
found_member = False
for items in (bodypart.get_peripheral(), bodypart.get_options()):
if not items:
continue
for item in items:
if item['name'] != s_item[1]:
continue
else:
found_member = True

if s_item[0] == "hapi_gpio_t":
_hal_gpio = "hal_gpio_%s_%d" % (
item['name'], bodypart_id)
_hapi_gpio = "hapi_gpio_%s_%d" % (
item['name'], bodypart_id)
data['hapi_gpio_vars'].append(
"hal_gpio_t %s;" % _hal_gpio
)
data['hapi_gpio_vars'].append(
"hapi_gpio_t %s = {%s, (void*)&%s};" % (
_hapi_gpio, item['value'], _hal_gpio)
)
data['struct_values'].append("&%s" % _hapi_gpio)
elif item['type'].startswith("char["):
data['struct_values'].append('"%s"' % item['value'])
else:
data['struct_values'].append("%s" % item['value'])

if not found_member and "dummy" not in s_item[1]:
raise Exception("Invalid struct member %s for %s" % (
str(s_item), c_struct_name))
return data

def _gen_plugin_states(self):
states = []
for bodypart in self.bodyparts:
Expand All @@ -164,7 +228,7 @@ def _gen_bodypart_items(self):
class BusListCPP(SourceGenerator):

TPL = Template("""
#include "sa_transports_list.h"
#include "sa_bus_list.h"
""")

def __init__(self, buses):
Expand Down
6 changes: 3 additions & 3 deletions smartanthill/network/commstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ def from_client_callback(self, message, properties):
self._source_id = message.source
data = message.data
assert isinstance(data, bytearray)
data.insert(0, self.device_id) # destination id
data.insert(1, 0x01) # first packet in chain
data.insert(2, 0x02) # SACCP_NEW_PROGRAM
# data.insert(0, self.device_id) # destination id
data.insert(0, 0x01) # first packet in chain
data.insert(1, 0x02) # SACCP_NEW_PROGRAM
self._protocol.send_data(
CommStackClientProtocol.PACKET_DIRECTION_CLIENT_TO_COMMSTACK,
data
Expand Down

0 comments on commit 43bd911

Please sign in to comment.