diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8426febd31d102532ad1b2641bfd3ce5ba3b6872
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,28 @@
+DYNAMIXEL_VERSION=$(shell git describe --tags | sed -e 's/^v//;s/-/_/g' )
+
+all:
+
+.PHONY: model
+model:
+	echo Add wget rules
+
+.PHONY: TAR
+TAR:
+	git archive \
+		--prefix dynamixel-$(DYNAMIXEL_VERSION)/ \
+		--output dynamixel-$(DYNAMIXEL_VERSION).tar.gz -- HEAD
+
+.PHONY: dynamixel-$(DYNAMIXEL_VERSION).spec
+dynamixel-$(DYNAMIXEL_VERSION).spec: dynamixel.spec.template Makefile
+	sed -e 's/__DYNAMIXEL_VERSION__/$(DYNAMIXEL_VERSION)/' $< > $@
+
+.PHONY: SRPM
+SRPM:	dynamixel-$(DYNAMIXEL_VERSION).spec TAR
+	rpmbuild --define "_sourcedir $$(pwd)" -bs $<
+
+clean:
+	rm -f *~
+	rm -f dynamixel-*.spec
+	rm -f dynamixel-*.tar.gz
+
+
diff --git a/dynamixel-0.1.spec b/dynamixel-0.1.spec
new file mode 100644
index 0000000000000000000000000000000000000000..6072da7b6c300016f4aad7ab63890e1ff3e47bbe
--- /dev/null
+++ b/dynamixel-0.1.spec
@@ -0,0 +1,47 @@
+Name:           dynamixel
+Version:        0.1
+Release:        1
+Summary:        Wrapper for Dynamixel SDK
+License:        Apache 2.0
+Source0:        https://gitlab.control.lth.se/anders_blomdell/dynamixel/-/archive/master/dynamixel-0.1.tar.gz
+
+%define debug_package %{nil}
+
+%if 0%{!?python3_pkgversion:1}
+%define python3_pkgversion 3
+%endif
+
+BuildRequires:  python3-devel
+Requires:  dynamixel-sdk
+
+%description
+Wrapper for Dynamixel SDK
+
+%package python%{python3_pkgversion}
+Summary: Python3 support files for %{name}
+Requires: %{name} = %{version}-%{release}
+
+%description python%{python3_pkgversion}
+Wrapper for Dynamixel SDK
+
+%prep
+%setup -q -n %{name}-0.1
+
+
+%build
+make DYNAMIXEL_VERSION=%{version}
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+
+# Python
+export DYNAMIXEL_VERSION=%{version}
+%{__python3} setup.py install -O1 \
+             --root=$RPM_BUILD_ROOT --prefix /usr \
+             --record=INSTALLED_python3
+
+%files
+
+%files python%{python3_pkgversion} -f INSTALLED_python3
+%defattr(-,root,root,-)
+
diff --git a/dynamixel.spec.template b/dynamixel.spec.template
new file mode 100644
index 0000000000000000000000000000000000000000..02eb1f12e5ff035458b8dd671734d94130e0cdfc
--- /dev/null
+++ b/dynamixel.spec.template
@@ -0,0 +1,47 @@
+Name:           dynamixel
+Version:        __DYNAMIXEL_VERSION__
+Release:        1
+Summary:        Wrapper for Dynamixel SDK
+License:        Apache 2.0
+Source0:        https://gitlab.control.lth.se/anders_blomdell/dynamixel/-/archive/master/dynamixel-__DYNAMIXEL_VERSION__.tar.gz
+
+%define debug_package %{nil}
+
+%if 0%{!?python3_pkgversion:1}
+%define python3_pkgversion 3
+%endif
+
+BuildRequires:  python3-devel
+Requires:  dynamixel-sdk
+
+%description
+Wrapper for Dynamixel SDK
+
+%package python%{python3_pkgversion}
+Summary: Python3 support files for %{name}
+Requires: %{name} = %{version}-%{release}
+
+%description python%{python3_pkgversion}
+Wrapper for Dynamixel SDK
+
+%prep
+%setup -q -n %{name}-__DYNAMIXEL_VERSION__
+
+
+%build
+make DYNAMIXEL_VERSION=%{version}
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+
+# Python
+export DYNAMIXEL_VERSION=%{version}
+%{__python3} setup.py install -O1 \
+             --root=$RPM_BUILD_ROOT --prefix /usr \
+             --record=INSTALLED_python3
+
+%files
+
+%files python%{python3_pkgversion} -f INSTALLED_python3
+%defattr(-,root,root,-)
+
diff --git a/dynamixel/model/mx_106t_r_2.0.py b/dynamixel/model/mx_106t_r_2_0.py
similarity index 98%
rename from dynamixel/model/mx_106t_r_2.0.py
rename to dynamixel/model/mx_106t_r_2_0.py
index cbb9d72da2f4a6ab1e7da491d1fbf589b649b9d2..3baedf82ca2a96edf570042c2d5170ac81fb3f27 100644
--- a/dynamixel/model/mx_106t_r_2.0.py
+++ b/dynamixel/model/mx_106t_r_2_0.py
@@ -3,7 +3,7 @@ from dynamixel.servo import Servo
 from dynamixel.servo import Row, RWRow, IndirectRow
 from dynamixel.channel import Protocol2
 
-class MX_106T_R_2.0(Servo):
+class MX_106T_R_2_0(Servo):
     EEPROM = {
         'model_number': Row(name='model_number', address=0, size=2, default=321),
         'model_information': Row(name='model_information', address=2, size=4, default=None),
@@ -65,4 +65,4 @@ class MX_106T_R_2.0(Servo):
     PROTOCOL = Protocol2
 
     def __init__(self, channel, id):
-        super(MX_106T_R_2.0, self).__init__(channel=channel, id=id)
+        super(MX_106T_R_2_0, self).__init__(channel=channel, id=id)
diff --git a/dynamixel/model/mx_28t_r_at_ar_2.0.py b/dynamixel/model/mx_28t_r_at_ar_2_0.py
similarity index 98%
rename from dynamixel/model/mx_28t_r_at_ar_2.0.py
rename to dynamixel/model/mx_28t_r_at_ar_2_0.py
index 7553e377b816bcd08d30b699874e134e8bb524d9..c1898b4ca050e215e7992b504309f5cf52e98885 100644
--- a/dynamixel/model/mx_28t_r_at_ar_2.0.py
+++ b/dynamixel/model/mx_28t_r_at_ar_2_0.py
@@ -3,7 +3,7 @@ from dynamixel.servo import Servo
 from dynamixel.servo import Row, RWRow, IndirectRow
 from dynamixel.channel import Protocol2
 
-class MX_28T_R_AT_AR_2.0(Servo):
+class MX_28T_R_AT_AR_2_0(Servo):
     EEPROM = {
         'model_number': Row(name='model_number', address=0, size=2, default=30),
         'model_information': Row(name='model_information', address=2, size=4, default=None),
@@ -63,4 +63,4 @@ class MX_28T_R_AT_AR_2.0(Servo):
     PROTOCOL = Protocol2
 
     def __init__(self, channel, id):
-        super(MX_28T_R_AT_AR_2.0, self).__init__(channel=channel, id=id)
+        super(MX_28T_R_AT_AR_2_0, self).__init__(channel=channel, id=id)
diff --git a/dynamixel/model/mx_64t_r_at_ar_2.0.py b/dynamixel/model/mx_64t_r_at_ar_2_0.py
similarity index 98%
rename from dynamixel/model/mx_64t_r_at_ar_2.0.py
rename to dynamixel/model/mx_64t_r_at_ar_2_0.py
index 579f736912fdfa52ade582ad7e5d2603f604b62a..914b303357ea8b270e6f9f64732e1b2d3d807882 100644
--- a/dynamixel/model/mx_64t_r_at_ar_2.0.py
+++ b/dynamixel/model/mx_64t_r_at_ar_2_0.py
@@ -3,7 +3,7 @@ from dynamixel.servo import Servo
 from dynamixel.servo import Row, RWRow, IndirectRow
 from dynamixel.channel import Protocol2
 
-class MX_64T_R_AT_AR_2.0(Servo):
+class MX_64T_R_AT_AR_2_0(Servo):
     EEPROM = {
         'model_number': Row(name='model_number', address=0, size=2, default=311),
         'model_information': Row(name='model_information', address=2, size=4, default=None),
@@ -65,4 +65,4 @@ class MX_64T_R_AT_AR_2.0(Servo):
     PROTOCOL = Protocol2
 
     def __init__(self, channel, id):
-        super(MX_64T_R_AT_AR_2.0, self).__init__(channel=channel, id=id)
+        super(MX_64T_R_AT_AR_2_0, self).__init__(channel=channel, id=id)
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000000000000000000000000000000000000..1c6e2016b404926504839afe166bc238e836e383
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+from distutils.core import setup, Extension
+
+try:
+    import os
+    VERSION=os.environ['DYNAMIXEL_VERSION']
+except KeyError:
+    VERSION='_UNKNOWN_'
+    pass
+
+setup(
+    name        = 'python-dynamixel',
+    version     = VERSION,
+    description = 'Python wrapper to the Dynamixel I/O library',
+    long_description = 'Python wrapper to the Dynamixel I/O library',
+    author      = 'Anders Blomdell',
+    author_email = 'anders.blomdell@control.lth.se',
+    url         = 'http://gitlab.control.lth.se/anders_blomdell/dynamixel.git',
+    license     = 'Apache 2.0',
+    platforms   = 'Linux',
+    packages    = [ 'dynamixel',
+                    'dynamixel.channel',
+                    'dynamixel.model',
+                    'dynamixel.servo' ]
+)
diff --git a/tools/html2py.py b/tools/html2py.py
index 89171fc83e5d188041670ba869da34d52f3e7aef..24f50c3c789b7f0dc9f677496911d9a730ffe775 100755
--- a/tools/html2py.py
+++ b/tools/html2py.py
@@ -179,7 +179,8 @@ def Parse(path):
                          .replace('/', '_')
                          .replace('(', '_')
                          .replace(')', '')
-                         .replace('+', ''))
+                         .replace('+', '')
+                         .replace('.', '_'))
                 if m := re.match('^2(.*)$', title):
                     title = f'DUAL-{m.group(1)}'
                     pass