AQI Sensor

The air quality in NYC has been . . . not great this summer. This presents and opportunity. Why settle for knowing that the air is not great in the city when you can know how not-great it is in your very own home?

Wow’d by Marty McGuire’s ability to check the air quaility of his apartment on his phone, I decided I would copy him by building a worse implementation of his setup. The features of my version of this setup include:

  • Check the PM2.5 levels in my apartment
  • Check the local AQI
  • Display the PM2.5 and AQI levels with LEDs
  • Display the PM2.5 and AQI levels on a screen
  • Chart the curent and historical PM2.5 levels on a website that I can access with my phone outside the house

In order to make this happen I needed:

The process is pretty straightforward. Every few minutes, the board checks the PM2.5 level. It then changes the LEDs at the top of the FunHouse accordintly, displays the number on the screen, and uploads the data to an Adafruit IO dashboard. At the same time, it also pulls the local AQI levels from the AQI API and updates the LEDs and screen accordingly.

The entire script is available in this repo. In addition to the script you will need:

  • The library files, which are also in the repo (make sure everything in the /lib folder in the repo is in the /lib folder on the board)
  • A secrets.py file to hold your wifi and Adafruit IO credentials. You can learn how to create that here.
  • A seperate keys.py file. This is for the AQI API. I’m sure there’s a way to incorporate this into the secrets.py file, but I couldn’t quite figure out the syntax. In any event, the entire contents of the file is AQI_URL = "the_url_with_your_api_key". You can create your URL by playing around with the AirNow API.

The Code

Here’s a walkthrough of the code.

This first block just imports all of the libraries and sets up the FunHouse object. If you are running into problems with libraries, make sure you have the library in you /lib folder on the device.

import time
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
from adafruit_pm25.i2c import PM25_I2C
from adafruit_funhouse import FunHouse

#for the external API
import adafruit_requests as requests
import keys
import socketpool
import ssl
import wifi

#for the light sensor mapping
from adafruit_simplemath import map_range


reset_pin = None

funhouse = FunHouse(default_bg=None)

The next chunk creates a few more objects, turns on wifi, and sets up variables for the AQI download. It uses the existing funhouse network elements to set up the requests object.

# Create library object, use 'slow' 100KHz frequency!
i2c = board.I2C()
# Connect to a PM2.5 sensor over I2C
pm25 = PM25_I2C(i2c, reset_pin)

print("Found PM2.5 sensor, reading data...")

# Turn on WiFi
funhouse.network.enabled = True
print("wifi on")
# Connect to WiFi
funhouse.network.connect()
print("wifi connected")

#these variables sets up the requests
pool = socketpool.SocketPool(wifi.radio)
requests = funhouse.network._wifi.requests

These are the variables for the various sensor readings.

#IO Stuff
FEED_2_5 = "2pointfive"
TEMP_FEED = "temp"
HUM_FEED = "humidity"
TEMPERATURE_OFFSET = (
    3  # Degrees C to adjust the temperature to compensate for board produced heat
)

These are the RGB color values as variables to make them slightly easier to work with.

#Colors
BLACK = (0,0,0)
GREEN = (0,228,0)
YELLOW = (255, 255, 0)
ORANGE = (255,40,0)
RED = (255,0,0)
PURPLE = (143,63,151)
MAROON = (126,0,35)

This next bit creates the text blocks that will be used to display the readings. The first and third ones are the reading labels. The second and fourth are the actual readings. They are much larger. The last line pushes them to the screen.

#text
funhouse.display.show(None)
pm_label = funhouse.add_text(
    text_scale = 2, text_position = (10,10), text_color = 0x606060
)
pm_value = funhouse.add_text(
    text_scale = 12, text_position = (90,60), text_color = 0x606060
)
aqi_label = funhouse.add_text(
    text_scale = 2, text_position = (10,110), text_color = 0x606060
)
aqi_value = funhouse.add_text(
    text_scale = 12, text_position = (60,180), text_color = 0x606060
)
funhouse.display.show(funhouse.splash)

With all of that set up, the rest of the code is in a While loop that just runs forever.

First, it reads the PM2.5 data from the sensor

try:
    aqdata = pm25.read()
    # print(aqdata)
except RuntimeError:
    print("Unable to read from sensor, retrying...")
    continue

Then it pushes the PM2.5, temp, and humidity data to Adafruit IO. The temp and humidity come from sensors that are built into the FunHouse.

# Push to IO using REST
    try:
        funhouse.push_to_io(FEED_2_5, aqdata["pm25 env"])
        funhouse.push_to_io(TEMP_FEED, funhouse.peripherals.temperature - TEMPERATURE_OFFSET)
        funhouse.push_to_io(HUM_FEED, funhouse.peripherals.relative_humidity)
        print("data pushed")
    except:
        print("error uploading data, moving on")

This section downloads the AQI data from the API. It reads the target URL from the keys.py file, downloads the payload, parses the json, and assigns the AQI value to a new variable. The AQI API website is not the most user friendly UX in the world, but I did end up narrowing my query down to a single monitoring station. AQI will be set to 0 if there is an error, which will serve as a signal that something is wrong.

    # get remote AQI data
    # #https://learn.adafruit.com/adafruit-funhouse/getting-the-date-time   
    target_URL = keys.AQI_URL
    
    try:
        response = requests.get(target_URL, timeout = 10)
        #print(response)
        jsonResponse = response.json()
        print(jsonResponse[0]["AQI"])
        currentAQI = jsonResponse[0]["AQI"]
    except:
        currentAQI = 0
        print('request failed')

The next section sets the text on the display. The labels are just one line each to set the text.

The actual reading display is more complicated. Using the AirNow AQI calculation data sheet, the if/elif statements set the color of the reading to match the alert color.

    #text stuff
    #set the label
    funhouse.set_text("PM 2.5", pm_label)
    #set the color for the pm2.5 reading
    if aqdata["pm25 env"] <= 12.0:
        funhouse.set_text_color(GREEN, pm_value)
    elif 12.0 < aqdata["pm25 env"] <= 35.4:
        funhouse.set_text_color(YELLOW, pm_value)
    elif 35.4 < aqdata["pm25 env"] <= 55.4:
        funhouse.set_text_color(ORANGE, pm_value)   
    elif 55.4 < aqdata["pm25 env"] <= 150.4:
        funhouse.set_text_color(RED, pm_value)
    elif 15.4 < aqdata["pm25 env"] <= 250.4:
        funhouse.set_text_color(PURPLE, pm_value)
    elif 25.4 < aqdata["pm25 env"] <= 500.4:
        funhouse.set_text_color(MAROON, pm_value)
    #set the reading
    funhouse.set_text(aqdata["pm25 env"], pm_value)
    #set the aqi label
    funhouse.set_text("AQI", aqi_label)
    #set the aqi color
    if currentAQI <= 50.0:
        funhouse.set_text_color(GREEN, aqi_value)
    elif 50.0 < currentAQI <= 100:
        funhouse.set_text_color(YELLOW, aqi_value)
    elif 100 < currentAQI <= 150:
        funhouse.set_text_color(ORANGE, aqi_value)   
    elif 150 < currentAQI <= 200:
        funhouse.set_text_color(RED, aqi_value)
    elif 200 < currentAQI <= 300:
        funhouse.set_text_color(PURPLE, aqi_value)
    elif 300 < currentAQI <= 500:
        funhouse.set_text_color(MAROON, aqi_value)
    funhouse.set_text(currentAQI, aqi_value)

After working through the display, things move on to the five LEDs built into the top of the FunHouse. First I create variables and set them all to off.

    #LED Stuff
    #https://www.airnow.gov/sites/default/files/2020-05/aqi-technical-assistance-document-sept2018.pdf
    #set all of the LEDs to black by default
    led_0 = BLACK
    led_1 = BLACK
    led_2 = BLACK
    led_3 = BLACK
    led_4 = BLACK
    print ("2.5 = " + str(aqdata["pm25 env"]))

Then the first two are updated based on the local PM2.5 reading and the last two are updated based on the local AQI.

    #update first two leds depending on the 2.5 reading
    if aqdata["pm25 env"] <= 12.0:
        led_0 = GREEN
        led_1 = GREEN
    elif 12.0 < aqdata["pm25 env"] <= 35.4:
        led_0 = YELLOW
        led_1 = YELLOW
    elif 35.4 < aqdata["pm25 env"] <= 55.4:
        led_0 = ORANGE
        led_1 = ORANGE   
    elif 55.4 < aqdata["pm25 env"] <= 150.4:
        led_0 = RED
        led_1 = RED 
    elif 15.4 < aqdata["pm25 env"] <= 250.4:
        led_0 = PURPLE
        led_1 = PURPLE 
    elif 25.4 < aqdata["pm25 env"] <= 500.4:
        led_0 = MAROON
        led_1 = MAROON

    #update the last two LEDs based on AQI
    if currentAQI <= 50.0:
        led_3 = GREEN
        led_4 = GREEN
    elif 50.0 < currentAQI <= 100:
        led_3 = YELLOW
        led_4 = YELLOW
    elif 100 < currentAQI <= 150:
        led_3 = ORANGE
        led_4 = ORANGE   
    elif 150 < currentAQI <= 200:
        led_3 = RED
        led_4 = RED
    elif 200 < currentAQI <= 300:
        led_3 = PURPLE
        led_4 = PURPLE
    elif 300 < currentAQI <= 500:
        led_3 = MAROON
        led_4 = MAROON

Finally, the new colors are pushed to the LEDs themselves

    #update the LEDs
    funhouse.peripherals.set_dotstars(led_0, led_1, led_2, led_3, led_4)

The LEDs are pretty bright. That’s helpful during the day, but it is a bit much at night. The next bit dims the LEDs based on ambient light. It uses the light sensor built into the FunHouse and maps the readings to a 0-1 scale, which is the scale used to control the brightness of the LEDs.

It is possible control the brightness of the LEDs individually (the syntax is (R,G,B,Brightness)), but in this case I want all of them to be the same level.

    #set LED brightness so they aren't super bright at night
    #map_range works (inputnumber, orig min, orig max, new min, new max)
    #right reading bounds appear to be ~1800-54000, real world is closer to 1800-5000)
    #goal here is to make the lights bright when it is bright and dim when it is dark
    brightness = map_range(funhouse.peripherals.light, 1800, 6000, 0, 1)
    print(brightness)
    funhouse.peripherals.dotstars.brightness = brightness

Finally, everything just waits for 2 minutes before starting over again.

time.sleep(120)
More on the Shifting State of Open Source Hardware

Earlier this week PT over at Adafruit published an interesting post on the evolving relationship between some of the larger open source hardware companies and open source itself. The post catalogs various ways in which three marquee open source hardware companies - Arduino, Sparkfun, and Prusa - have explored non-open strategies for various parts of their offerings.

Generally speaking, I think it is fine for companies to use open source when it is useful and not use open source when it is not useful, as long as they are being upfront about it. Open source is a strategy, and no single strategy applies in every situation. This can become a problem when open source messaging is used to draw users into non-open hardware or systems. Although PT groups Arduino, Sparkfun, and Prusa together for the purposes of the post, I don’t think he intends to suggest that they are all guilty of that, or even that they are engaging with non-openness to the same degree. As of today, I think it is fair to say that the three companies represent a broad range of relationships to open source.

In this context, I also worry about recession from open source. If open source is a strategy, and some high profile open source hardware companies feel like they need to move away from it in various ways, that may be a red flag that there are aspects of the open approach that we as a community should be considering more deeply. To that end, the thing I really want from these companies is for them to talk about their thinking and decisionmaking. Just as many of us have learned from their decisions to use open source, there could be a lot to learn from their decisions to not use open source in some cases.

That is why I find the end of PT’s piece so interesting. It includes an interview-style comment with Josef Prusa discussing his article from March (I had some thoughts about it when it was originally published).

I want to give Prusa credit for raising these concerns, and for talking about them publicly. It is easy to not talk about these decisions publicly, precisely because doing so results in people asking the type of follow up questions that PT asks in his post, I ask in my post, and fellow OSHWA Board Member Thea Flowers raised in her post. I also want to recognize that his answers to PT lead with the admission that Prusa hasn’t finished their homework to follow up to their original article, so everything he says should be understood as a work in progress.

And Yet

All that being said, I find parts of Prusa’s answer to be incredibly frustrating! The core of that frustration is that he raises a bunch of facially valid concerns, and then says that those concerns are pushing them to look at closed-source options, but does not explain how going closed-source addresses the concerns.

This is a style of (potentially) backing away from open hardware that goes back at least as far as Makerbot’s switch over a decade ago. Part of me wants to assume that there is something to it, because it feels like a recurring pattern. The other part of me can’t help but notice that no one seems to be able to actually explain why open source is the driver of the problems they describe. I want to see someone connect the dots.

Prusa’s comment identified a number of problems that they feel like they are dealing with:

  • Chinese government subsidies for competitors
  • Patent applications based on open-source community inventions (unclear if he is limiting these to Prusa inventions, or open source inventions generally)
  • Competitors violating existing licenses
  • The need to protect IP and the inability to do so under current licenses

I’m very willing to believe that these are real challenges. I just don’t understand how becoming less open addresses any of them.

Becoming less open will not reduce the Chinese government (or any other country) from supporting competitors. That support is driven by an interest in creating a strong position in an industry, not by the fact that some of the players in the industry are open.

Becoming less open seems unlikely to impact how much you care about other parties applying for patents in other countries. It seems unlikely that Prusa will decide to spend money filing international patents themselves. If they do find themselves accused of infringement (which, again, would only happen if the country they were selling into was also a country where someone else had obtained a patent), they’re going to have to pay to challenge the patent either way. Furthermore, if someone really wants to understand and copy an innovation built into a desktop 3D printer, not having open documentation seems unlikely to be a major barrier (I’d love to understand why/if I’m wrong about that).

Becoming less open will not change the fact that competitors are violating existing licenses. If competitors are already violating existing licenses, how would adding new layers of licenses change the dynamic? If I’m being honest, this is always the one that makes the least sense to me. No one has ever been able to explain the logic chain of:

  • We can’t enforce existing licenses based on our intellectual property when they are being violated
  • We add new license terms to that same intellectual property that mean that people violate our licenses even more
  • Suddenly we are able to enforce our license terms

If there is a magic trick to enforce more restrictive licenses, why doesn’t it work when someone violates your open license? Isn’t a license violation a license violation?

Asking these questions always makes me feel like I’m missing some key part of the decisionmaking process. That’s why I was excited to see Prusa’s original post, and encouraged that he continued to engage with PT’s questions this week. I really hope that Prusa’s full follow up article begins to shed light on some of these questions. While I’m sure doing so will lead to some criticism, it could also be incredibly helpful for the community to really understand the nature of these challenges.

Feature image: Political Discussion in a Lumber Shanty from the Smithsonian Open Access collection

Keep 3D Printers Unlocked (2023)

Update 8/2023: It looks like no one opposed the renewal request (celebrate the absence of opposition comments listed at the bottom of this page). That should mean that the renewal is approved when this process wraps up in a few months. I’ll post an update when that happens, or if something looks like it might prevent it from happening.

Once again, it is time for the US Copyright Office to revisit its decision to legalize breaking Digital Rights Management (DRM) for specific purposes. The default rule in the United States is that breaking digital locks on copyright-protected works is illegal, so the every-three-year Copyright Office process is designed to create exemptions for groups with good reasons to break those digital locks.

In the past, I have helped to create an exemption for breaking DRM that prevents you from using whatever material you want in your 3D printer (here are all of the previous posts discussing that process). Last time around, I helped tweak some of the language in that exemption in order to make it as clear as possible.

This time around could be very straightforward. I’ve just submitted a request to renew the current exemption without any changes. If no one opposes the request, the Copyright Office could recommend it be renewed without any additional work. That would mean it stays legal to break DRM if you want to use materials of your choice in a 3D printer. However, if someone does oppose the renewal, or the Copyright Office declines to recommend renewal for any reason, it will trigger a more expansive process.

I’m hopeful that the request will end up being uncontroversial and the Copyright Office recommends renewal. While there have been companies opposed to the exemption in the past, that opposition dropped off in the most recent cycle.

The Copyright Office maintains a page for this process where you can track all of the exemption requests. Oppositions to renewal requests are due towards the end of the summer, which is probably the next opportunity for any news. I will post about any updates when they come.

A(nother) Reply to Josef Průša

Last week Josef Průša, the eponymous proprietor of the important open source hardware company Prusa Research, shared a post about the state of open source in 3D printing.

This is exciting. One of the things I like so much about the open source hardware community is how broadly it embraces openness. That includes having open, public conversations about what it means to do open source hardware, and to run an open source hardware company.

The Prusa post raises some interesting questions. Some of them are new. Others may not be as new (although that does not mean that they are resolved). Thea Flowers (not incidentally, like me, also an OSHWA board member) has already jumped in to the conversation the post calls for with a reply. It’s a thoughtful one, and if you care about these questions I would strongly recommend reading it.

A big part of the Prusa post talks about legal issues and licenses. This is something I have THOUGHTS and OPINIONS about, which means I have a few questions. Those questions tend to be about getting more specific information about the types of problems the Prusa post identifies, and about the types of control it assumes it can impose via license. Right now, I feel like I don’t fully understand the problem, or how an intellectual property-based license might address it.

Before getting into the legal stuff, I want to touch on one or two other things.

Goals are Important

One of the things I really appreciated about the Prusa post is this statement:

But community development isn’t the main reason why we offer our products as open source. Our main goal has always been to make our printers easy to maintain and modify, so people and companies can play and experiment with software and hardware.

(emphasis in original)

The thing I really appreciate about this statement is that it articulates a goal for using an open source approach. Open source hardware is a strategy. Like any strategy, it is appropriate in some situations but not others. Also, like any strategy, it is not magic. (more about this in the 2020 Open Source Hardware Weather Report.

Articulating a goal for using open source hardware gives you a way to evaluate your strategy. You can decide if it is working, if it is the best way to achieve your goal, and if you need to invest more or less in it.

Is open source helping Prusa Research achieve its goals in a way that justifies the cost? I’m not sure. I am glad that they have something concrete to use to evaluate it.

Assertions I am Less Sure About

The Prusa post also makes some assertions about the nature and state of open source hardware. I’m not convinced that either of them are true, although I am open to being convinced. I would love to see a deeper discussion about both of them, and more data about the second point to the extent that it exists.

Assertion #1: Open Source Relies on Everyone Playing by the Rules

The Prusa post says:

The open-source movement relies on the fact that everyone involved plays by the same rules.

(emphasis in original)

I’m not sure that has ever been the case, or that it even should be the case. Open source absolutely relies on some critical mass of people playing by the same rules (Phillip Torrone famously started the process of trying to codify some common rules for open source hardware back in 2012). What makes up a “critical mass” will vary depending on the community and the nature of the work they are doing.

That being said, there are always going to be people outside of the community. Many of those people will benefit from the work of the community without contributing to it, or caring about it, or even being aware of its existence. Some of those people may even “exploit” the community (although, as Thea points out, that line can be a hard one to draw when you start looking at it closely). That’s ok, as long as there are enough people in the community to achieve its goals. To a first approximation, all open source communities operate in this environment.

Put another way, open source relies on enough people playing by the same rules to keep the community engaged. Someone outside of the community benefitting from the community’s work in a way the community views as unreasonable can absolutely cause people to leave. And if enough people leave there is a problem. But the mere existence of these people is not fatal to any open source community. Viewing open source community challenges as a universal compliance problem could cause you to come to all sorts of inaccurate conclusions.

Assertion #2: The Situation is Changing

The Prusa post also says:

But in recent years, I feel that the situation is changing. More and more companies are breaking and bending the rules, and the community is not nearly as resistant to their actions as it once was.

(emphasis in original)

This is a strong assertion. If it is true it would be very interesting. However, I don’t know that we have very much evidence of a major change (yet).

Open source hardware companies have struggled with actors outside of the community for years (“Cloning ain’t cool” is one of the unofficial rules from 2012). We’ve seen claims that companies are breaking the rules - and that rule breaking is pushing open source hardware companies away from being open - since at least the time of Makerbot’s decision to back away from open source.

Are things different now? Maybe? On its face, the concerns that the Prusa post raises seem fairly similar to those raised by Bre Pettis around Makerbot clones in 2012. They have been echoed by other companies in the decade since. Like Prusa, I suspect many other open source hardware company leaders have lamented that “After a minor internet storm, the situation calms down, and the code remains closed (or only part of it is opened), and after a few weeks, everyone forgets.” after their hardware is cloned by a competitor.

I would actually love to hear more from Prusa about how he understands the nature of this dynamic to have changed over the years. Absent that, while the situation may feel different within Prusa Research, I’m not sure we have enough evidence to say that it has changed for open source hardware in general. And if things have changed within Prusa Research, I’d love to know more about that too!

I think it is useful to think about new open source licenses, about the goals you want them to achieve, and not get too bogged down in whether or not those new licenses are goals are compatible with “open source” as a platonic ideal (that’s part of the reason I was excited to participate in creating the ml5.js ethical open source license).

However, licenses are not self-executing or self-enforcing. Nor are they the only way to enforce behavioral norms. They rely on people deciding to enforce them, and actual rights to license. Therefore, when thinking about creating a new license, it can be helpful to understand the current state of affairs and why that state is not working. To that end, I have a bunch of questions:

What is Prusa Research currently doing to enforce its existing rights, and how are those efforts falling short?

Trademarks are usually the most powerful rights an open source hardware company has. What trademarks does Prusa have? Does it take steps to patrol their use (say, on large online marketplaces)? If it is, and that is not working, why not? If it isn’t, why not?

(by the way, a panel on how successful open source hardware companies enforce their rights would be a super interesting Open Hardware Summit panel that I will absolutely be proposing next year)

What About the CERN Licenses?

Open source hardware companies often have copyrights as well. The Prusa post states (correctly) that the GPL license is not really optimized for open source hardware. However, while the GPL is imperfect when it comes to hardware, it does exist. Have there been violations of that license? If so, did Prusa pursue them? Why or why not? If not, why would a more restrictive license change their approach?

Perhaps more importantly, has Prusa looked at the new(ish) CERN licenses? How might its enforcement experience change under that regime? How do those licenses fail to address the problems in the market? Are those failures curable with different license language, or are they inherent to the types of intellectual property rights that attach to a 3D printer?

Are There Specific Examples of Bad Behavior That Could be Controlled by a License?

Some parts of 3D printers cannot be protected by any intellectual property rights (see this whitepaper for more). Without a right to license, the terms of the license do not matter. Therefore, it would be helpful for Prusa to provide specific (or specific-ish) examples of what it considers bad behavior that would violate a more restrictive hardware license.

The Prusa post talks about not releasing electronics plans for the new MK4 printer. I don’t know how easy those boards would be to reverse engineer. I do know that it is unlikely that they are protected by any sort of intellectual property right that could be licensed in a way that would control other users. Thinking about new licenses would be easier with a clear understanding of the type of behavior that the license is intended to control.

The end of the Prusa post includes a list of working points that could form the core of a new license. In thinking about how to incorporate them into a license, I have some clarifying questions:

How would you think about defining “clearly stating” authorship on the product or software?

  • If you’re using some code or blueprints to bring software or hardware to market, the original code’s authorship must be clearly stated on the product or in the software. Additionally, deleting copyright information from headers and history from repositories is prohibited.

Naming authors can be straightforward when there are only one or two. Slic3r has 103 contributors. PrusaSlicer is built on Slic3r and has 166 (I don’t know how many of those users overlap). Do each of these people need to be listed? What happens if they disagree about what it means to be “clearly” listed? Is it ok to provide a hyperlink to a page that lists all of them, or do their names (or handles, or both) need to be contained on the product itself? If it needs to be contained on the product, do we need to talk about minimum font sizes? If there is a fight about the clarity of notice, how is that fight resolved?

How would you think about defining a clone?

  • The production of nearly exact 1:1 clones for commercial purposes is not allowed.

In trying to understand if a clone is a copy, should we look at all of the elements of the first piece of hardware, or just the contributions that the first hardware manufacturer made? Does it matter if any of those contributions are eligible for any sort of intellectual property protection? Are those contributions listed somewhere so that someone knows how to avoid being accused of being a clone? Is “nearly” calculated as a raw number (“we made 10 contributions and you copied nine”) or as some sort of weighted percentage (“we made 10 contributions, and you copied the three most important ones”)?

What is a license for manufacturing spare parts actually licensing?

  • License for manufacturing spare parts is valid for service, modification, or educational purposes.
  • Upgrades and additional modifications based on original parts are allowed and welcome.
  • Parts that can be considered consumables (e.g., thermistors, heater blocks, fans, printing plates, etc.) can be manufactured and sold commercially after the verification by the licensor based on the presentation of samples.

Some points seem to assume that a manufacturer of a piece of hardware gets to control all third party parts for that hardware. This is not usually the case. In what situations would anyone actually need a license to manufacture spare parts? What about consumables (ask the manufacturers of 2D printers who keep trying - and failing - to force people to buy replacement toner from them how that is going)? What rights would someone be violating if they manufactured spare replacement parts/consumables without the license?

What does it mean to cease activity?

  • If the licensor ceases its activity, the non-commercial clause is terminated.

Sometimes companies totally disappear. Other times, they are acquired, or they merge, or their assets are put up for auction. The final point states that the non-commercial clause is terminated if the licensor ceases its activities. Why is ceasing activity a trigger for that, and should any of these kind-of-stopping-but-not-quite-stopping activities trigger it too?

What Does This License License?

There is one meta-question threaded through much of this post - what rights, exactly, would this new license be licensing? This question is always important (at least to lawyers like me) but it becomes more important as the license becomes more restrictive. I might not be sure if I am legally bound by the Creative Commons Attribution license on a piece of hardware, but it’s pretty easy to give attribution just in case. If the licensor is trying to limit non-commercial uses of that hardware, I will care a lot more about what might trigger that restriction (and how to sidestep it).

None of my questions - including this final one - are intended to be gotcha questions, or to nit pick this proposal to pieces. As I said at the top, I think this is an interesting conversation, and it is one I want to take seriously. For me, taking it seriously means thinking about what kinds of information would be helpful when considering it. That’s what I’ve tried to do here.

I hope this does end up being a real discussion in the open source hardware community. I’m also open to being convinced that we need to do something new. However, in order to be convinced, I need more information than I have right now.

Feature image: Political Discussion in a Lumber Shanty from the Smithsonian Open Access collection

Maybe LLMs Won’t Raise 230 Questions?

Recently I read two blog posts about the intersection of Section 230 and generative AI, specifically LLMs. While they are both interesting, I think they skip over a potentially limiting constraint on the importance of these questions: the blast radius of any specific piece of AI generated content on a website. Specifically, it seems plausible that blast radius - or damaging reach of the piece of content - may be fairly limited, which would reduce the likelihood that 230 protections end up being super relevant.*

I agree with Professor Matt Perault in Lawfare that Section 230 does not currently cover content generated by generative AI managed/hosted/whatever by a given website. I also agree with John Bergmayer over at the Public Knowledge blog that this state of affairs is a good one, at least for now.

Where I may disagree with them is how often this kind of thing is likely to come up in a context that feels 230-familiar. (I say “may” because both of them are focused on a different part of this analysis, so I don’t know how they feel about this). AI is already raising legal issues, and websites will host third party material created by AI. But today’s deployment of AI may not raise new 230 issues.

One standard 230 fact pattern is Person A posts content on Website B. Person C objects to that content (because it defames them, or causes them some other harm), and sues Website B for hosting it. In most cases, Section 230 allows Website B to step aside, telling Person C to sue Person A if they don’t like the content.

A key element of this pattern is usually that Person A’s potentially harmful content is available for many people to see. That makes the potential blast radius for harmful information quite large.

However, current generative AI usage patterns tend to be a bit different. Services like Microsoft Bing’s Sydney, or DuckDuckGo’s DuckAssist are designed to create custom content for an audience of one. That content can be hugely problematic. But in most cases the output isn’t available more broadly. That could severely limit the blast radius for the harmful information. A reduced blast radius makes it less likely the harmed party will know about the harm, and that the harm will be significant enough to justify a lawsuit.

Of course, there are two other obvious scenarios where this type of AI could create 230 issues. One is where Person A uses a generative AI service to create content, and then brings that content to Website B. In that case, the fact that generative AI was used to create the content should not be particularly relevant to Website B’s ability to get out of the suit. It would not make very much sense to have a 230 carveout for harmful content that happened to be created by generative AI.

Which brings us to the other scenario. If Person A uses Website D to generate the problematic content, Website D might be pulled into any related litigation. That seems like a fact pattern outside of 230, and pretty much what Bergmayer is contemplating in his piece. In that case, it does seem to be at least facially reasonable to allow a court to explore Website D’s liability for the content. That could even be true if the Website D content just stays on Website D. While it would be harder to discover and document, Website D creating millions of bespoke pieces of content that slander Person C does feel like something that Website D could be sued for.

*I am super aware that projecting the future impact of technology based on current use patterns can be a recipe for disaster. Sorry future Michael for any problems or embarrassment this post causes you!

Feature image: Little Billy Bryan Chasing Butterflies from the Smithsonian National Portrait Gallery. I’m not going to pretend that it contains some larger commentary about this post. I was poking around looking for an image, happened to see this, and obviously needed to use it.