Skip to content

Commit

Permalink
Release v1.1 (#243)
Browse files Browse the repository at this point in the history
* PIR sensor implementation Issue #166 (#181)

* start PIR sensor implementation

* PIR sensor helper and controller updates

* fix spelling mistake in controller

* pir output to input changes

* pir output to input location changes

* added javadocs in helper and changed rgb colors

* address changes with yml and pir controller

* fix typo in pir controller

* Fixed Integration Bugs (#187)

* Fixed javadoc errors (#189)

* Javadoc errors (#190)

* Fixed javadoc errors

* removed javadoc from .gitignore

* Passive Buzzer Implementation (#182)

* Implemented passive buzzer helper

* Implemented passive buzzer controller and updated yaml to contain passive buzzer.

* Created additional test functions for the passive buzzer. Modified the sequence function.

* Refactored functions in helper to appropriately change frequencies. Corresponding function in the controller needs work to accept parameters from an array.

* Modified setFrequencies function to accept File as parameter. Has not been tested.

* Modified and tested the functionality of the Helper: setFrequencies method & Controller: defineFrequency method. Added comments for usage of the controller method to ensure ease of use.

* Resolved lack of javadoc comments

* Refactored function names and included appropriate javadoc comments

* Added javadoc comments

* resolved javadocs conflicts

---------

Co-authored-by: ruthvikm <[email protected]>

* Adoc Updates (#188)

* updating adocs

* how to use pi4micronaut

* how to use pi4micronaut adoc updates

* adoc updates

* indent fix

* adoc changes addressed

* adoc changes

* adoc link updates

* adoc indent fix

* adoc fix

* adoc final updates

* adoc final final updates

* Fixes LCD - closes issue #116 (#184)

* set lcd display to 2 rows instead of 4 rows

* test solution for lcd

* using i2cconfig in the lcd display constructor

* 32 bit note in asciidoc, new methods and controller stuff for lcd

* only working methods, and log info

* Added write text to position

---------

Co-authored-by: ruthvikm <[email protected]>
Co-authored-by: Ruthvik Mannem <[email protected]>

* outlined ultrasound sensor component (#185)

* outlined ultrasound sensor component

* Working ultra sonic sensor

* added javadocs for ultra sonic sensor classes

---------

Co-authored-by: ruthvikm <[email protected]>
Co-authored-by: Ruthvik Mannem <[email protected]>

* Updating develop (#193)

* Adding the new components from develop (#191)

* PIR sensor implementation Issue #166 (#181)

* start PIR sensor implementation

* PIR sensor helper and controller updates

* fix spelling mistake in controller

* pir output to input changes

* pir output to input location changes

* added javadocs in helper and changed rgb colors

* address changes with yml and pir controller

* fix typo in pir controller

* Fixed Integration Bugs (#187)

* Fixed javadoc errors (#189)

* Javadoc errors (#190)

* Fixed javadoc errors

* removed javadoc from .gitignore

* Passive Buzzer Implementation (#182)

* Implemented passive buzzer helper

* Implemented passive buzzer controller and updated yaml to contain passive buzzer.

* Created additional test functions for the passive buzzer. Modified the sequence function.

* Refactored functions in helper to appropriately change frequencies. Corresponding function in the controller needs work to accept parameters from an array.

* Modified setFrequencies function to accept File as parameter. Has not been tested.

* Modified and tested the functionality of the Helper: setFrequencies method & Controller: defineFrequency method. Added comments for usage of the controller method to ensure ease of use.

* Resolved lack of javadoc comments

* Refactored function names and included appropriate javadoc comments

* Added javadoc comments

* resolved javadocs conflicts

---------

Co-authored-by: ruthvikm <[email protected]>

* Adoc Updates (#188)

* updating adocs

* how to use pi4micronaut

* how to use pi4micronaut adoc updates

* adoc updates

* indent fix

* adoc changes addressed

* adoc changes

* adoc link updates

* adoc indent fix

* adoc fix

* adoc final updates

* adoc final final updates

* Fixes LCD - closes issue #116 (#184)

* set lcd display to 2 rows instead of 4 rows

* test solution for lcd

* using i2cconfig in the lcd display constructor

* 32 bit note in asciidoc, new methods and controller stuff for lcd

* only working methods, and log info

* Added write text to position

---------

Co-authored-by: ruthvikm <[email protected]>
Co-authored-by: Ruthvik Mannem <[email protected]>

* outlined ultrasound sensor component (#185)

* outlined ultrasound sensor component

* Working ultra sonic sensor

* added javadocs for ultra sonic sensor classes

---------

Co-authored-by: ruthvikm <[email protected]>
Co-authored-by: Ruthvik Mannem <[email protected]>

---------

Co-authored-by: Joe Folen <[email protected]>
Co-authored-by: adelgadoj3 <[email protected]>
Co-authored-by: Adrian Swindle <[email protected]>
Co-authored-by: jyanev <[email protected]>

* Fixed Signing Issue (#192)

* Fixed Signing Issue

* trying to fix Signing Issue

* trying to fix1 Signing Issue

* trying to fix2 Signing Issue

* Release

---------

Co-authored-by: Joe Folen <[email protected]>
Co-authored-by: adelgadoj3 <[email protected]>
Co-authored-by: Adrian Swindle <[email protected]>
Co-authored-by: jyanev <[email protected]>

* Revert "Updating develop (#193)" (#194)

This reverts commit 26c0345.

* added documentation for ultrasonic sensor

* Starting touch switch documentation

* added updated circuit images

* fixed issues w documentation

* further updates to touch switch documentation

* further further updates to touch switch documentation

* final updates to touch switch adoc

* final final updates to touch switch adoc

* addresses yml change in adoc

* Fixed unsatisfied dependency

* grammar fix

* Architecture diagram update. Issue 209 (#215)

* update architecture diagram in readme

* include file in readme

* actually include file in readme

* actually include file in readme

* deleted sections 4,5 from documentation; added descriptions for i2c, multipin, pwm

* 197 active buzzer documentation (#214)

* Created initial draft of Active Buzzer documentation, updated index.adoc with link, and added Circuit diagram

* Corrected error in assembly instructions

* Implemented requested changes and added schematic diagram

---------

Signed-off-by: adelgadoj3 <[email protected]>

* Passive Buzzer Documentation (#208)

* Began process for documentation. Needs functionality information.

* Added further information about functionality and overview.

* Incorporated requested changes: javadoc and example controller

* Implemented requested changes. buzzer-SD.png was added in with activebuzzer issue. Once that is merged the img conflict should resolve here.

* left out index.adoc fix for passive adoc link. Implemented

* Touch switch was not incorporated into the file.Causing two links to be on the same line. Should resolve conflict

* Didn't resolve conflict. Removed link.

---------

Signed-off-by: adelgadoj3 <[email protected]>

* PIR Sensor Documentation- fixes issue #200 (#216)

* pirsensor documentation draft

* pir sensor documentation

* fixed improve this doc link for pir

* fix spaces per request

Signed-off-by: Adrian Swindle <[email protected]>

---------

Signed-off-by: Adrian Swindle <[email protected]>

* added desc for debounce in digitalinput adoc

* Fixes #211 Blink Functionality for LED (#220)

* Implemeted blink functionality into the LEDHelper and LEDController.

* Updated .adoc with functionality.

* Removed comment for clarity of function

* updated issue-201; made changes to adocs

* updated component adocs

* fixed typos

* fixed typos

* corrections to adocs

* small edits to adocs

* Config Workflow Diagram in adoc. Issue #210 (#219)

* added config workflow image

* added commun with hardware adoc details

* added utilities description to commun adoc

* addresses changes requested

* final updates to adocs

* Fixed few documentation bugs

* Fixed few more bugs

* added info for components

* adjusted TOC width

* beginning servo motor implementation

* servo motor updates

* fixed rfid adoc (#226)

* servo motor updates

* servo motor updates

* setAngle update in helper

* arm moves inaccurately

* setAngle and map updates in helper

* updated map logic in helper

* Fixes #224 | Started basis of photoresistorSensor documentation (#227)

* Started basis of photoresistorSensor documentation

* Added the preliminary information for testing

* Added more information to the .adoc. Still need to add the Circuit Diagram

* Incorporated Circuit Diagram into .adoc, added .png file to img folder, and add ex tag to PhotoResistorController

* Updated .adoc with changes. Added index.adoc file with photoresistorSensor link.

* Provided accurate circuit diagram for photoresistor with help from Aswindle. Provided updated circuit diagram for LED also with help from Aswindle. Implemented further changes from comments within pull request.

---------

Co-authored-by: Alex Delgado <[email protected]>
Co-authored-by: Adrian Swindle <[email protected]>

* servo motor works for 0 to 180

* added tag in controller

* Fixes #230 | Servo Motor Documentation (#231)

* Created the basis of the Servo Motor documentation

* Implemented links to other files now that the controller and helper are merged. Need both Circuit Diagram & Schematic Diagram.

* Implemented circuit diag. & schematic diag. into .adoc. Added both diagrams to img folder.

* Implemented requested changes.

* Tilt Switch implementation. Issue #40 (#232)

* tilt switch controller and helper

* added javadocs to helper

* fixed error in TouchSwitchHelper

* added comments to controller

* Completes #233 :Micro Switch Implementation (#234)

* touch switch logger typo fix

* draft of micro switch helper, controller and application.yml

* fix injection in controller micro switch

* added controller comments

Signed-off-by: Adrian Swindle <[email protected]>

* debounced updated

Signed-off-by: Adrian Swindle <[email protected]>

---------

Signed-off-by: Adrian Swindle <[email protected]>

* Tilt switch documentation (#236)

* begin tiltSwitch docs and fix error in touchSwitch doc

* adding diagrams

* added assembly instructions

* Updated README.md (#239)

Signed-off-by: Ruthvik Mannem <[email protected]>

* added micro switch documentation (#240)

* Update documentation (#241)

* updated added_dependency.png

* doc bug fix

---------

Signed-off-by: adelgadoj3 <[email protected]>
Signed-off-by: Adrian Swindle <[email protected]>
Signed-off-by: Ruthvik Mannem <[email protected]>
Co-authored-by: Joe Folen <[email protected]>
Co-authored-by: adelgadoj3 <[email protected]>
Co-authored-by: Adrian Swindle <[email protected]>
Co-authored-by: jyanev <[email protected]>
Co-authored-by: jyanev <[email protected]>
Co-authored-by: Joe Folen <[email protected]>
Co-authored-by: Alex Delgado <[email protected]>
  • Loading branch information
8 people authored May 10, 2024
1 parent 532051b commit 47d44c2
Show file tree
Hide file tree
Showing 146 changed files with 3,948 additions and 3,227 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ out/
.classpath
.factorypath
*@*
Workflow.png
Workflow_Diagram.png
Pi4Micronaut_logo.png
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Pi4Micronaut is an innovative Java library crafted for developers who aim to bui

The existence of Pi4Micronaut is justified by the need for a robust, scalable, and efficient way to bridge the gap between enterprise-grade software and the physical world of hardware. It is particularly valuable for projects that demand both the high-performance, microservices-oriented capabilities of the Micronaut framework and the versatile hardware interaction that the Raspberry Pi offers. Whether it's for home automation, industrial monitoring, or educational purposes, Pi4Micronaut empowers developers to deliver reliable and sophisticated IoT applications that can run headless on a Raspberry Pi or be managed remotely, providing convenience, control, and customization to the end-users.

**Note:** Pi4Micronaut doesn't work with the latest Raspberry Pi 5 because of its whole new architecture. Pi4J and pigpio libraries doesn't provide support for Pi 5 yet. Look out for the latest version of Pi4J to work with Pi5's in the future.

### Information

- **Source Code:** <https://github.com/oss-slu/Pi4Micronaut/>
Expand All @@ -25,7 +27,7 @@ The existence of Pi4Micronaut is justified by the need for a robust, scalable, a
- **Adoption Date:** August 2022
- **Technologies Used:**
- Java
- Micronaut Framework
- Micronaut Framework with Gradle
- Pi4J Library
- **Type:** IOT (Raspberry Pi)
- **License:** [Apache License 2.0](https://opensource.org/license/apache-2-0/)
Expand All @@ -34,9 +36,16 @@ The existence of Pi4Micronaut is justified by the need for a robust, scalable, a
## Pi4Micronaut
- [Link to Pi4Micronaut Documentation](https://oss-slu.github.io/Pi4Micronaut/)
- [API Reference](https://oss-slu.github.io/Pi4Micronaut/javadoc/index.html)
- [Maven Central Repository](https://central.sonatype.com/artifact/io.github.oss-slu/pi4micronaut-utils)
- [Maven Artifacts](https://repo1.maven.org/maven2/io/github/oss-slu/pi4micronaut-utils/)

### Architecture Diagram
![Pi4Micronaut.png](Workflow.png)
![Pi4Micronaut.png](Workflow_Diagram.png)

## Example Projects using Pi4Micronaut Library
- [Home Automation](https://github.com/oss-slu/Pi4Micronaut/tree/Home_Automation)
- [Lab Automation](https://github.com/oss-slu/Pi4Micronaut/tree/Lab_Automation)
- [OSS SLU Checkin](https://github.com/oss-slu/SLU_OSS_CheckIn)

## Micronaut 3.7.3
- [Micronaut 3.7.3 User Guide](https://micronaut-projects.github.io/micronaut-docs-mn3/3.7.3/guide/index.html)
Expand Down
Binary file removed Workflow.png
Binary file not shown.
Binary file added Workflow_Diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/active-buzzer")
public class ActiveBuzzerController {

Expand Down Expand Up @@ -37,7 +38,7 @@ public void disableActiveBuzzer(){
}

/**
* Emits an beep sound from the active buzzer.
* Emits a beep sound from the active buzzer.
*/
@Get("/beepTone")
public void playBeepTone(){
Expand Down Expand Up @@ -65,4 +66,5 @@ public void morseCodeTest(){

activeBuzzerHelper.morseCodeTone();
}
}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/led")
public class LEDController {
private final LEDHelper ledHelper;
Expand All @@ -28,4 +29,10 @@ public void ledOff(){
public void switchState(){
ledHelper.switchState();
}

@Get("/blink/{duration}/")
public void blink(int duration){
ledHelper.blink(duration);
}
}
//end::ex[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.opensourcewithslu.components.controllers;

import com.opensourcewithslu.inputdevices.MicroSwitchHelper;
import com.opensourcewithslu.outputdevices.LEDHelper;
import com.pi4j.io.gpio.digital.DigitalInput;
import com.pi4j.io.gpio.digital.DigitalOutput;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/microSwitch")
public class MicroSwitchController {

private final MicroSwitchHelper microSwitchHelper;

private final LEDHelper ledHelper1;
private final LEDHelper ledHelper2;


public MicroSwitchController(@Named("micro-switch") DigitalInput microSwitch,
@Named("led") DigitalOutput led1,
@Named("led2") DigitalOutput led2) {
this.microSwitchHelper = new MicroSwitchHelper(microSwitch);
this.ledHelper1 = new LEDHelper(led1);
this.ledHelper2 = new LEDHelper(led2);
}
//enables the micro switch. The LEDs will switch states as the switch is pressed
@Get("/enable")
public void enableMicroSwitch() {
microSwitchHelper.addEventListener(e -> {
if (microSwitchHelper.isPressed) {
ledHelper1.ledOff();
ledHelper2.ledOn();

}
else {
ledHelper1.ledOn();
ledHelper2.ledOff();
}
});
}
//disable the micro switch
@Get("/disable")
public void disableMicroSwitch() {
microSwitchHelper.removeEventListener();
}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.opensourcewithslu.inputdevices.PIRSensorHelper;
import com.opensourcewithslu.outputdevices.RGBLEDHelper;
import com.opensourcewithslu.utilities.MultipinConfiguration;
import com.opensourcewithslu.utilities.MultiPinConfiguration;
import com.pi4j.io.gpio.digital.DigitalInput;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
Expand All @@ -11,33 +11,28 @@
/**
* The PIRSensorController class is used with the PIRSensorHelper class and RGBHelper class to implement a PIR motion sensor with an RGB LED light.
*/

//tag::ex[]
@Controller("/pirSensor")
public class PIRSensorController {

private final PIRSensorHelper pirSensorHelper;

private final RGBLEDHelper rgbledHelper;

/**
* The PirSensorController constructor.
* @param pirSensor A Pi4J DigitalInput object.
* @param rgbLed A MultiPinConfiguration object.
*/
public PIRSensorController(@Named("pir-sensor")DigitalInput pirSensor,
@Named("rgb-led-2")MultipinConfiguration rgbLed) {
public PIRSensorController(@Named("pir-sensor") DigitalInput pirSensor, @Named("rgb-led-2") MultiPinConfiguration rgbLed) {
this.pirSensorHelper = new PIRSensorHelper(pirSensor);
this.rgbledHelper = new RGBLEDHelper(rgbLed);
}

/**
* Enables the PIR sensor by adding an event listener which sets the RGB LED to red when movement is detected and green otherwise.
*/
@Get("/enable")
public void enablePIRSensor() {

int[] red = {255,0,0};
int[] green = {0,255,0};

pirSensorHelper.addEventListener(e -> {
if (pirSensorHelper.isMoving) {
rgbledHelper.setColor(red);
Expand All @@ -47,7 +42,6 @@ public void enablePIRSensor() {
}
});
}

/**
* Disables the controller by removing the event listener and turning off the RGB LED.
*/
Expand All @@ -56,5 +50,5 @@ public void disablePIRSensor() {
pirSensorHelper.removeEventListener();
rgbledHelper.ledOff();
}

}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.inject.Named;
import java.io.File;

//tag::ex[]
@Controller("/passive-buzzer")
public class PassiveBuzzerController {

Expand Down Expand Up @@ -94,4 +95,5 @@ public void playPiTone(){
passiveBuzzerHelper.piToneSequence();

}
}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.inject.Named;
import javax.validation.constraints.Positive;

//tag::ex[]
@Controller("/photoResistor")
public class PhotoResistorController {
private final LEDHelper ledHelper;
Expand Down Expand Up @@ -55,4 +56,5 @@ public String setThreshold(@Positive int i) {
return ("Darkness threshold set to "+ i + "\n");
}

}
}
//end::ex[]
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.opensourcewithslu.components.controllers;

import com.opensourcewithslu.inputdevices.RotaryEncoderHelper;
import com.opensourcewithslu.utilities.MultipinConfiguration;
import com.opensourcewithslu.utilities.MultiPinConfiguration;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;
Expand All @@ -11,7 +11,7 @@
public class RotaryEncoderController {
private final RotaryEncoderHelper encoderHelper;

public RotaryEncoderController(@Named("rotary-encoder")MultipinConfiguration rotaryEncoder){
public RotaryEncoderController(@Named("rotary-encoder") MultiPinConfiguration rotaryEncoder){
this.encoderHelper = new RotaryEncoderHelper(rotaryEncoder);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.opensourcewithslu.components.controllers;

import com.opensourcewithslu.outputdevices.ServoMotorHelper;
import com.pi4j.io.pwm.Pwm;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/servoMotor")
public class ServoMotorController {

private final ServoMotorHelper servoMotorHelper;

public ServoMotorController(@Named("servo-motor")Pwm servoMotor) {
this.servoMotorHelper = new ServoMotorHelper(servoMotor);
}

@Get("/enable")
public void enableServoMotor() {
servoMotorHelper.enable();
}

@Get("/disable")
public void disableServoMotor() {
servoMotorHelper.disable();
}

@Get("/setAngle/{angle}")
public void setAngle(int angle) {
servoMotorHelper.setAngle(angle);
}
}
//end::ex[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.opensourcewithslu.components.controllers;

import com.opensourcewithslu.inputdevices.TiltSwitchHelper;
import com.opensourcewithslu.outputdevices.LEDHelper;
import com.pi4j.io.gpio.digital.DigitalInput;
import com.pi4j.io.gpio.digital.DigitalOutput;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/tiltSwitch")
public class TiltSwitchController {

private final TiltSwitchHelper tiltSwitchHelper; // controls the tilt switch
private final LEDHelper ledHelper; // controls the LED

public TiltSwitchController(@Named("tilt-switch-input")DigitalInput tiltSwitch,
@Named("led2")DigitalOutput led) {
this.tiltSwitchHelper = new TiltSwitchHelper(tiltSwitch);
this.ledHelper = new LEDHelper(led);
}

// The 'enable' method adds an event listener that listens for changes in the tilt switch
// If it is tilted, the LED turns on and off otherwise
@Get("/enable")
public void enableTiltSwitch() {
tiltSwitchHelper.addEventListener(e -> {
if (tiltSwitchHelper.isTilted) {
ledHelper.ledOn();
}
else {
ledHelper.ledOff();
}
});
}

// The disable method removes the event listener
@Get("/disable")
public void disableTiltSwitch() {
tiltSwitchHelper.removeEventListener();
}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.micronaut.http.annotation.Get;
import jakarta.inject.Named;

//tag::ex[]
@Controller("/touchSwitch")
public class TouchSwitchController {

Expand Down Expand Up @@ -37,4 +38,5 @@ public void enableTouchSwitch() {
public void disableTouchSwitch() {
touchSwitchHelper.removeEventListener();
}
}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import jakarta.inject.Named;


//tag::ex[]
@Controller("/ultraSound")
public class UltraSonicSensorController {

Expand Down Expand Up @@ -55,3 +56,4 @@ public String disableUltrasoundSensor() {
return "Ultra Sonic Sensor Disabled";
}
}
//end::ex[]
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/**
* Controller for managing LCD1602 display operations via HTTP requests.
*/
//tag::ex[]
@Controller("/lcd")
public class lcdController {
private final LCD1602Helper lcdHelper;
Expand All @@ -37,10 +38,10 @@ public String writeDataAtPos(@PathVariable String text, @PathVariable int line,
return "Text written at line " + line + ", position " + pos + ": " + text + "\n";
}

@Get("/write/character/{charvalue}")
public String writeCharacter(@PathVariable char charvalue) {
lcdHelper.writeCharacter(charvalue);
return "Character '" + charvalue + "' written to LCD\n";
@Get("/write/character/{charValue}")
public String writeCharacter(@PathVariable char charValue) {
lcdHelper.writeCharacter(charValue);
return "Character '" + charValue + "' written to LCD\n";
}

@Get("/backlight/{state}")
Expand Down Expand Up @@ -68,3 +69,4 @@ public String turnOff() {
return "Display turned off\n";
}
}
//end::ex[]
Loading

0 comments on commit 47d44c2

Please sign in to comment.