Visit Blog Page

Transmitter | Sprachschule

transmitter-front.png This project represents an extended collaboration between the school's director, the designer, and myself. It launched officially in January 2018. The backend runs on a Ubuntu-Postgres-Nginx-Python stack with Django/Mezzanine.
transmitter-calendar.png Custom online course catalog and registration system; completely controllable by the school's staff. Staff can easily add a new batch of courses with assigned teachers, all of which are instantly available for student applications.
transmitter-calendar.png Easy-to-use article and event publishing features for staff with built-in features for social media previews allow for constant engagement with current and future students.
transmitter-admin.png Feature-rich online system for administration offers automatic invoice generation for students, payment tracking, and email students with all relevant information.
transmitter-coursesheets.png All teachers have a custom login that allows them to view relevant course information for all current and upcoming classes, including student info and requisite course materials.
alejandro-front.png My role was to entirely redesign an existing website and rebuild from scratch. The client required a clean, simple way to showcase their cinematographic and photographic work. This project runs on Python/Django.
alejandro-pics.png The client can now edit and create new photo series and upload new images. All images are automatically resized and watermarked for quick and easy display on the site.
detcon-front.png The previous developer regrettably used a popular online website service, which resulted in a site that was bloated, slow, and inefficient. I completely rewrote the code, reduced total file size by 95%, and greatly improved the user's mobile experience.
detcon-admin.png This site runs on a quick and simple vanilla Django interface for interacting with key bits of text and images -- allowing the admin to efficiently add or remove staff members and change existing information.
aynur-front.png In this project, the client had an extensive portfolio which needed a strong presentation and the option of simple future modification.
aynur-admin.png This site runs on a Django/Wagtail CMS backend which enables the client to completely customize all portfolio pages and text content without technical assistance.
a full stack dev handles both levels of web development: I prefer to work with well-structured PostgreSQL or MySQL databases in conjunction with Memcached for fast delivery. For larger projects, I incorporate revision history and daily cloud backups. The internet now demands responsive, dynamic sites. Your site must look great on a wide variety operating systems, browser versions, and screen resolutions.
I work with custom configured cloud Ubuntu servers running Nginx and deployment using Docker containers. Solid security, total configurability, rapid development. Every project has different requirements, but where appropriate I love Python-based frameworks like Django in conjunction with a CMS like Wagtail or Mezzanine. This enables me to provide a website that is custom-tailored to your project requirements. I build your site bespoke. No pre-crafted generic templates; just optimized HTML/CSS and JavaScript. The end result? Lightning fast sites.

Thank you!

Your message has been delivered.

Something went wrong!

Email me here: hello at dylanh dot net.

Compal CH7466CE Automatic Restart


Sept. 1, 2018

The CH7466CE is a cable modem and wireless router that came with our plan from our ISP. I found it needed a reboot every couple of days or connection speeds would be a bit sluggish.

The simplest way to reboot is to pull the plug and wait three minutes for it to restart. Alternatively here's a bit of Python code to automate the process and force the machine to reboot late in the night, when your connection isn't in use.

This uses Python 3.6 since f-strings (PEP 498) make things a bit more elegant. Only dependency is Requests - again for the sake of elegance and simplicity.

First let's define our constants. I've left default router settings in place, but you'll want to change these as needed.

import requests

ROUTER_IP = '192.168.0.1'
LOGIN_URI = f'http://{ROUTER_IP}/common_page/login.html'
SETTER_URI = f'http://{ROUTER_IP}/xml/setter.xml'
USERNAME = 'admin'
PASSWORD = 'password'

Next we're going to create a basic Connection class. It will instantiate a new Requests session to be used through the process and will define two tokens which will later be provided by the router.

class Connection:
    def __init__(self):
        self.session = requests.Session()
        self.user_token = ''
        self.admin_token = ''

We'll hit the server with a GET request and extract the data from a sessionToken cookie. We'll need this data before progressing any further.

class Connection:
    ....
    def set_user_token(self):
        response = self.session.get(LOGIN_URI)
        if response.status_code == 200:
            print('Connected to login page.')
            self.user_token = response.cookies.get('sessionToken')

We've saved the sessionToken data to our user_token variable. Now let's wrap up this data along with the login and password. This bundle will be sent as JSON in a POST to the router's webserver.

class Connection:
    ....
    def set_admin_token(self):
        post_params = [('token', self.user_token), ('fun', '15'),
                       ('Username', USERNAME), ('Password', PASSWORD)]
        response = self.session.post(SETTER_URI, data=post_params)
        if response.text == 'successful':
            print('Successfully logged into router.')
            self.admin_token = response.cookies.get('sessionToken')

If the login succeeds, the server will provide us with a new sessionToken. Using this new token will give us elevated permissions for a variety of functions. Adding 'fun': '15' a JSON field here will reboot the router. Other numbers perform different functions - many of which do not require admin access but still display potentially sensitive router information or reset the router back its factory default.

class Connection:
    ....
    def reboot(self):
        post_params = [('token', self.admin_token), ('fun', '8')]
        self.session.post(SETTER_URI, data=post_params)
        print('Rebooting router. Please wait about 2.5 minutes.')

The final steps needed are here:

if __name__ == '__main__':
    c = Connection()
    c.set_user_token()
    c.set_admin_token()
    c.reboot()

If on Windows, you can use Task Scheduler to run this at a specific time at regular intervals. If on Linux/Mac, you can run crontab -e from bash prompt and add something like this:

0 4 * * * python3 /path/to/script.py

dylan hayward