School Bell System

April 20, 2018 at 05:48 pm

This is a fairly simple bell system that I wrote for a school. It uses a C++ daemon to read a XML config file, which can be created using a web UI written in PHP (and HTML, CSS, and Javascript). The daemon can 1) write to a serial port or a usb-to-serial converter that is connected to a triac circuit powering the actual bell, 2) set GPIO pins high, or 3) execute a command.

Code on Github

You need is a circuit that will turn on and off the bell when the voltage on one of the pins of a serial connector (or usb-to-serial-converter) goes from low to high. Or, you need to setup a circuit that operates based on your GPIO signal. Or, you need to create some script or program to execute to ring the bell.

See the Github page at the link above to install this on Raspbian.

Note: You want to make sure the clock is right, but I think Raspbian installs ntp by default.


Web UI is Optional
No, you don't really need it. It is just there so that people who don't want to edit the config.xml file by hand can have a nice pretty website to use.

Website looks odd in <browser name> (e.g. IE 5, 6, 7)
Yes, I spent a lot of time trying to get the calendar to show up above text boxes in IE7. I eventually just gave up since I don't use it and most computers running windows have at least IE8. If you know how to fix it, modify it and do a pull request on Github (or email me or something). I'm using

Web Server
The PKGBUILD and whatnot are all for Apache because that is what I have been using. If you decide to use the web UI, all you have to do is have a web server that will work with PHP. If you modify the PKGBUILD to work with another web server, I would be happy to see it.

Bell rings again when daemon is restarted
If you restart the bell system daemon during a minute when the bell is supposed to ring, it will ring again since it checks if a bell should ring during this minute on start. I'm not entirely sure it is worth trying to fix this since I doubt this happens more than once or twice... I just want you to be aware that it could happen.

There are Bugs
If you find one, or when you find one, create an issue on Github.


This School Bell System is primarily designed to be used:

  • for school bell systems that have weekly schedules and occasionally days without bells or with a different schedule (such as a half day)
  • with a bell system connected to a serial port of the Linux computer it is running on OR with a bell system connected to a Raspberry Pi computer

Using Web UI

The Web UI is an optional method to modify the config file for those who don't want to modify the XML code directly. If you just installed the software on a computer, be sure to read the first two sections below.

Setting up your first schedule

Go to the Schedules page and click the + button to add a new schedule. Type in a name for the schedule (used to identify it on the Calendar page) in the text box. Click the + button below the text box to add a first time. Click the button again for a second time. If you want to reorder the times, drag the :: on the left side of the time up or down. If you want to delete a time, click the red "x" next to it. If you want to delete a schedule, click the red "x" next to the text box. When you are done creating the schedule, click the Save button on the right side of the page.

Note: Times are displayed and stored in 24-hour time.

Go to the Calendar page and choose what days you want this to be the default schedule by selecting it in the drop down box next to the days of the week. If you want it to be the default schedule on Wednesday, select it in the drop down box next to Wednesday.

Still on the calendar page are two other sections: Quiet Periods and Override Schedules. If you want to have the bells not ring for a day, click the Add link next to "Quiet Periods" and click on the new item created. Select the start date for when to start not ringing. If this is a single day, only set the start date. If this is for more than a day, also set the end date. If this is for a certain period of time during a day (or more), also set the Start time and End time to the right. By default the bell will not ring from 0:00 to 23:59 (the entire day) during the range or single date you select. If you only want it to not ring between 7:00 and 7:30, set those to be the start and end times during the day or days you wish. The process is the same for adding Overriding schedules such as a half day. Click add and click the new item. With override schedules, you will also have to specify what schedule to use on the day/days you specify. To delete any of these calendar items, click the red "x" to the left. To reorder them, drag them up or down in the list. You cannot drag them between Quiet Periods and Override Schedules.

Setting up the Bell System Settings

Before your bell system will actually ring, you need to set when school starts and ends by going to the Settings page. Click on the text box next to "School Start" to bring up a calendar. Choose the day when school starts and do likewise for the day school ends. The bell will only ring between these two dates.

Note: These dates include years. Don't forget to set them to the correct year.

Also change the length of the ring in seconds to anywhere between 1 and 10 seconds. The default is 3 seconds. If you need to change this to over 10 seconds, you will need to modify the constants in the PHP code for the Web UI and the C++ code for the daemon.

Backup and Restore

Occasionally, you will want to backup the bell system settings, schedules, and calendar. To download a backup, go to the Backup page and click "Download Config." Save this file somewhere. If you ever need to return to this revision, just go back to the Backup page and select this file under Restore and click "Save" to restore it.

Changing Password

To change the password for the Web UI, you need to run "sudo bellsystem-password" again. To change the password for the Linux user run "sudo passwd username."

I can't save changes

You can try running "sudo chown www-data /usr/share/webapps/bellsystem/config.xml" to change ownership of the config file. You need to do this if you ever manually replace the file, which might have caused the user to change. They should both be what apache is running PHP as (on Raspbian this appears to be "www-data", on Arch Linux ARM this is user "http" and group "http").

Modifying The XML File

If you choose not to use the Web UI, you can modify the config.xml file directly. An example config file is available in the directory you installed from or online here. There are three sections to the XML file: settings, calendar, and schedules.


These elements should be specified:

  • length - The length in seconds that the bell will ring. It must be between 1 and 10; otherwise, modify the C++ daemon.
  • device - This should be either /dev/ttyUSB0 or /dev/ttyACM0 for a USB-to-Serial converter or something like /dev/ttyS0 or /dev/ttyAMA0 for a serial port.
  • method - This should have any of "gpio", "serial", or "command" separated by commas for the methods you wish to use to ring the bell. Note: presently you should have only one of these enabled since they won't all run at the same time.
  • command - This is the command to execute when command mode is enabled.
  • gpio_pin - This is the list of GPIO pins to set high when GPIO is enabled (e.g. when on a Raspberry Pi).
  • start - The date that school starts and the bells [possibly] will start ringing. It must be in YYYYMMDD (e.g. 20111101).
  • end - This is the date that school ends and the bells will stop ringing. It is in the same format.


There should be three elements:

  • default - This should have seven exec elements each either blank or with the ID of a schedule that is the default on that day. The day first exec is Sunday, the second Monday, etc.
  • quiet - This is a list of days when the bells will not ring. Format explained below.
  • override - This is a list of when the default schedule will be overrided with another schedule. Format explained below.

A "when" is slightly different for the quiet and override items, but the text of it is the same. It can be:

  • YYYYMMDD - a single day
  • YYYYMMDD-YYYYMMDD - a range of days
  • YYYYMMDDHHMM-YYYYMMDDHHMM - a range of days starting and ending at a certain time on the start and end days (this functionality is not available in the Web UI); the HHMM is two-digit hour followed by two-digit minute.

A when can have up to three attributes. If this is under override, it must have the "exec" attribute.

  • exec - This is required for the override schedules. It is the ID of the schedule that will override the default during this date/time period.
  • start - This is optional. It is the time during each of the days that will start being quiet or this override schedule.
  • end - This is optional. It is the time during each of the days that will end being quiet or this override schedule.

Sometimes the YYYYMMDDHHMM and start/end attributes confuse people. (That's why the YYYYMMDDHHMM isn't available in the Web UI.) For example, for a quiet period, the YYYYMMDD0730-YYYYMMDD0830 would start not ringing at 7:30 on the first day and stop not ringing at 8:30 on the second day. A "start='7:30' end='8:30'" would stop the bell from ringing between 7:30 and 8:30 on each of the days during the days specified. Yes, these end up being identical if the range of days is a single day.


There could be any number of elements under this. Each one is a schedule element with two attributes:

  • id - This is normally a number from 0-infinity (should work though even if it is a string). This is used to identify which schedule is the default on which days and which schedule is used to override the default schedule on certain days.
  • name - This is just to help you. It's not really necessary, but it will/should give an error if not specified. It is more used in the Web UI.

Under each schedule element should be any number of time elements. These should be in the format H:MM or HH:MM (e.g. 8:00 and 12:35).