From 9062dc54b8dad57d010e2db17e7fcb206d7bfb2d Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sun, 29 Sep 2019 11:22:13 +0200 Subject: [PATCH] Init --- .gitignore | 3 + LICENSE | 165 +++++++++++++++++++++++++ README.md | 35 ++++++ Soundbutton/Program.cs | 105 ++++++++++++++++ Soundbutton/Properties/AssemblyInfo.cs | 36 ++++++ Soundbutton/Soundbutton.csproj | 74 +++++++++++ Soundbutton/dpkg/control | 9 ++ Soundbutton/dpkg/create-Builds.bat | 3 + Soundbutton/dpkg/make-deb.sh | 54 ++++++++ Soundbutton/dpkg/postinst | 13 ++ Soundbutton/dpkg/preinst | 2 + Soundbutton/dpkg/prerm | 7 ++ Soundbutton/dpkg/soundbutton-logrotate | 10 ++ Soundbutton/dpkg/soundbutton.service | 19 +++ Soundplayer.sln | 61 +++++++++ 15 files changed, 596 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Soundbutton/Program.cs create mode 100644 Soundbutton/Properties/AssemblyInfo.cs create mode 100644 Soundbutton/Soundbutton.csproj create mode 100644 Soundbutton/dpkg/control create mode 100644 Soundbutton/dpkg/create-Builds.bat create mode 100644 Soundbutton/dpkg/make-deb.sh create mode 100644 Soundbutton/dpkg/postinst create mode 100644 Soundbutton/dpkg/preinst create mode 100644 Soundbutton/dpkg/prerm create mode 100644 Soundbutton/dpkg/soundbutton-logrotate create mode 100644 Soundbutton/dpkg/soundbutton.service create mode 100644 Soundplayer.sln diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18d294 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.vs +/Soundbutton/bin +/Soundbutton/obj diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..153d416 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ff01bb --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Sound-Button + +## Install + +### Dependencies + +#### Mono +* sudo apt-get install apt-transport-https dirmngr gnupg ca-certificates +* sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +* echo "deb https://download.mono-project.com/repo/debian stable-raspbianbuster main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list +* sudo apt-get update +* sudo apt-get install mono-runtime + +#### GPIO +* sudo raspi-config +* 5 Interfacing Options +* P8 Remote GPIO +* sudo apt-get install wiringpi + +#### Audioplayer +* sudo apt-get install mpg321 + +### Programm +* sudo dpkg -i armhf-soundbutton_1.0-0.deb + +### Audiofiles +* 1.mp3 oder 1.wav in /home/pi kopieren (Schalter 1). +* 2.mp3 oder 2.wav in /home/pi kopieren (Schalter 2). + +## Start +* mono /usr/local/bin/soundbutton/Sound-Button.exe eingeben und testen ob alles klappt. +* sudo systemctl start soundbutton.service zum starten, ist auch im Autostart, jedoch nach der ersten Installation läuft das Programm nicht selbstständig und beendet sich ohne Sounddateien auch sofort! + +## Logging +* tail /var/log/soundbutton.log -f eingeben und sehen was die Logdatei ausgibt. diff --git a/Soundbutton/Program.cs b/Soundbutton/Program.cs new file mode 100644 index 0000000..068b5bb --- /dev/null +++ b/Soundbutton/Program.cs @@ -0,0 +1,105 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using BlubbFish.Utils; +using BlubbFish.Utils.IoT.Bots; +using Unosquare.RaspberryIO; +using Unosquare.RaspberryIO.Gpio; + +namespace BlubbFish.Soundbutton { + class Program : ABot { + private String Schalter1Audio = ""; + private String Schalter2Audio = ""; + private GpioPin Schalter1; + private GpioPin Schalter2; + private Boolean playing = false; + + static void Main(String[] args) => new Program(); + + Program() { + this.logger.SetPath("/var/log/soundbutton.log"); + this.FindAudio(); + this.RegisterGPIO(); + this.WaitForShutdown(); + this.Dispose(); + } + + private void RegisterGPIO() { + this.Schalter1 = Pi.Gpio.Pin07; + this.Schalter1.PinMode = GpioPinDriveMode.Input; + this.Schalter1.InputPullMode = GpioPinResistorPullMode.PullDown; + this.Schalter1.RegisterInterruptCallback(EdgeDetection.RisingEdge, this.Schalter1Switched); + + this.Schalter2 = Pi.Gpio.Pin00; + this.Schalter2.PinMode = GpioPinDriveMode.Input; + this.Schalter2.InputPullMode = GpioPinResistorPullMode.PullDown; + this.Schalter2.RegisterInterruptCallback(EdgeDetection.RisingEdge, this.Schalter2Switched); + } + + private async void AudioPlayer(String audiofile, GpioPin pin) => await Task.Run(() => { + if(this.playing) { + return; + } + this.playing = true; + Boolean start = true; + while(pin.Read() || start) { + start = false; + Console.WriteLine("Playing Audio: " + audiofile); + Process p = new Process(); + p.StartInfo.Arguments = audiofile; + if(audiofile.ToLower().EndsWith("mp3")) { + p.StartInfo.FileName = "mpg321"; + } else if(audiofile.ToLower().EndsWith("wav")) { + p.StartInfo.FileName = "aplay"; + } + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.UseShellExecute = false; + p.Start(); + p.WaitForExit(); + Console.WriteLine(p.StandardOutput.ReadToEnd()); + Console.WriteLine("Playing Done!"); + } + this.playing = false; + }); + + private void Schalter2Switched() { + if(this.playing) { + return; + } + this.AudioPlayer(this.Schalter2Audio, this.Schalter2); + } + + + + private void Schalter1Switched() { + if(this.playing) { + return; + } + this.AudioPlayer(this.Schalter1Audio, this.Schalter1); + } + + private void FindAudio() { + String[] filePaths = Directory.GetFiles("/home/pi/"); + foreach(String item in filePaths) { + if(Regex.Match(item, "1.(mp3|wav)", RegexOptions.IgnoreCase).Success) { + this.Schalter1Audio = item; + } + if(Regex.Match(item, "2.(mp3|wav)", RegexOptions.IgnoreCase).Success) { + this.Schalter2Audio = item; + } + } + if(this.Schalter1Audio == "" || this.Schalter2Audio == "") { + Helper.WriteError("Audofiles nicht gefunden! (1.mp3 oder 1.wav, 2.mp3 oder 2.wav in /home/pi)"); + throw new ArgumentException("Audofiles nicht gefunden! (1.mp3 oder 1.wav, 2.mp3 oder 2.wav in /home/pi)"); + } + } + + public override void Dispose() { + base.Dispose(); + this.Schalter1.RegisterInterruptCallback(EdgeDetection.ExternalSetup, null); + } + } +} diff --git a/Soundbutton/Properties/AssemblyInfo.cs b/Soundbutton/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f70b8a5 --- /dev/null +++ b/Soundbutton/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("Soundbutton")] +[assembly: AssemblyDescription("Playing a sound on click of a button")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("BlubbFish")] +[assembly: AssemblyProduct("Soundbutton")] +[assembly: AssemblyCopyright("Copyright © 2019 - 29.09.2019")] +[assembly: AssemblyTrademark("BlubbFish")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("fd9451f4-ca65-4cf4-8ccc-1e29c0f657a7")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0")] +[assembly: AssemblyFileVersion("1.0.0")] diff --git a/Soundbutton/Soundbutton.csproj b/Soundbutton/Soundbutton.csproj new file mode 100644 index 0000000..0ab9c43 --- /dev/null +++ b/Soundbutton/Soundbutton.csproj @@ -0,0 +1,74 @@ + + + + + Debug + AnyCPU + {FD9451F4-CA65-4CF4-8CCC-1E29C0F657A7} + Exe + BlubbFish.Soundbutton + Sound-Button + v4.7.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + {8C5D4DE9-377F-4EC8-873D-6EEF15F43516} + Unosquare.RaspberryIO + + + {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9} + Bot-Utils + + + {FAC8CE64-BF13-4ECE-8097-AEB5DD060098} + Utils + + + + \ No newline at end of file diff --git a/Soundbutton/dpkg/control b/Soundbutton/dpkg/control new file mode 100644 index 0000000..302f072 --- /dev/null +++ b/Soundbutton/dpkg/control @@ -0,0 +1,9 @@ +Package: soundbutton +Version: x.x-x +Section: base +Priority: optional +Architecture: any +Depends: mono-runtime (>= 5.16.0), mpg321 (>= 0.3.2), wiringpi (>= 2.50) +Maintainer: BlubbFish +Description: Soundplayer + for playing sound on button clicks diff --git a/Soundbutton/dpkg/create-Builds.bat b/Soundbutton/dpkg/create-Builds.bat new file mode 100644 index 0000000..901cc2f --- /dev/null +++ b/Soundbutton/dpkg/create-Builds.bat @@ -0,0 +1,3 @@ +mkdir ..\..\..\Builds +bash.exe -c "./make-deb.sh armhf" +pause \ No newline at end of file diff --git a/Soundbutton/dpkg/make-deb.sh b/Soundbutton/dpkg/make-deb.sh new file mode 100644 index 0000000..89e0485 --- /dev/null +++ b/Soundbutton/dpkg/make-deb.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +HOMEDIR=$HOME +ROOT="$HOMEDIR/deb" +OUTPUT="../bin/Release" + +EXEC="$ROOT/usr/local/bin/soundbutton" +#CONFIG="$ROOT/etc/loramap" +SYSTEMD="$ROOT/lib/systemd/system" +LOGROTATE="$ROOT/etc/logrotate.d" + +DEBIAN="$ROOT/DEBIAN" +VMAJOR=$(grep -e "^\[assembly: AssemblyVersion(\"" ../Properties/AssemblyInfo.cs | cut -d'"' -f 2 | cut -d'.' -f 1) +VMINOR=$(grep -e "^\[assembly: AssemblyVersion(\"" ../Properties/AssemblyInfo.cs | cut -d'"' -f 2 | cut -d'.' -f 2) +VBUILD=$(grep -e "^\[assembly: AssemblyVersion(\"" ../Properties/AssemblyInfo.cs | cut -d'"' -f 2 | cut -d'.' -f 3) +ARCHT=$1 + +mkdir -p $EXEC +#mkdir -p $CONFIG +mkdir -p $DEBIAN +mkdir -p $SYSTEMD +mkdir -p $LOGROTATE + +cp control $DEBIAN +cp preinst $DEBIAN +cp postinst $DEBIAN +cp prerm $DEBIAN +sed -i s/Version:\ x\.x-x/"Version: $VMAJOR.$VMINOR-$VBUILD"/ $DEBIAN/control +sed -i s/Architecture:\ any/"Architecture: $ARCHT"/ $DEBIAN/control +chmod 755 $DEBIAN -R + +cp soundbutton.service $SYSTEMD +chmod 644 $SYSTEMD/soundbutton.service + +cp $OUTPUT/*.exe $EXEC/ +#cp $OUTPUT/gpio.2.44 $EXEC/ +#cp $OUTPUT/libwiringPi.so.2.44 $EXEC/ +find $OUTPUT -name \*.dll -exec cp {} $EXEC/ \; +chmod 644 $EXEC/* +chmod 755 $EXEC + +#cp $OUTPUT/resources $EXEC -r +#sed -i s/"
vx.x.x"/"
$VMAJOR.$VMINOR.$VBUILD"/ $EXEC/resources/index.html + +#cp $OUTPUT/config-example/* $CONFIG +#chmod 644 $CONFIG/* +#chmod 755 $CONFIG + +cp soundbutton-logrotate $LOGROTATE/soundbutton +chmod 644 $LOGROTATE/* + +dpkg-deb --build $ROOT +mv $HOMEDIR/deb.deb ../../../Builds/"$ARCHT-soundbutton_$VMAJOR.$VMINOR-$VBUILD.deb" +rm $HOMEDIR/deb -r \ No newline at end of file diff --git a/Soundbutton/dpkg/postinst b/Soundbutton/dpkg/postinst new file mode 100644 index 0000000..59b823c --- /dev/null +++ b/Soundbutton/dpkg/postinst @@ -0,0 +1,13 @@ +#!/bin/bash + +systemctl enable soundbutton +systemctl daemon-reload + +touch /var/log/soundbutton.log +chown root:root /var/log/soundbutton.log +chmod 644 /var/log/soundbutton.log + +if [ -f /tmp/soundbutton_service_runner ]; then + service soundbutton start + rm /tmp/soundbutton_service_runner +fi \ No newline at end of file diff --git a/Soundbutton/dpkg/preinst b/Soundbutton/dpkg/preinst new file mode 100644 index 0000000..05a7907 --- /dev/null +++ b/Soundbutton/dpkg/preinst @@ -0,0 +1,2 @@ +#!/bin/bash + diff --git a/Soundbutton/dpkg/prerm b/Soundbutton/dpkg/prerm new file mode 100644 index 0000000..482b3f4 --- /dev/null +++ b/Soundbutton/dpkg/prerm @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ $(systemctl is-active soundbutton || true) == "active" ]] +then + touch /tmp/soundbutton_service_runner + service soundbutton stop +fi \ No newline at end of file diff --git a/Soundbutton/dpkg/soundbutton-logrotate b/Soundbutton/dpkg/soundbutton-logrotate new file mode 100644 index 0000000..abe79ae --- /dev/null +++ b/Soundbutton/dpkg/soundbutton-logrotate @@ -0,0 +1,10 @@ +/var/log/soundbutton.log { + compress + copytruncate + daily + delaycompress + missingok + notifempty + rotate 4 + size=10M +} \ No newline at end of file diff --git a/Soundbutton/dpkg/soundbutton.service b/Soundbutton/dpkg/soundbutton.service new file mode 100644 index 0000000..9ec7b8e --- /dev/null +++ b/Soundbutton/dpkg/soundbutton.service @@ -0,0 +1,19 @@ +# If you modify this, please also make sure to edit init.sh + +[Unit] +Description=Sound-Button +After=network-online.target + +[Service] +User=root +Group=root +WorkingDirectory=/usr/local/bin/soundbutton +ExecStart=/usr/bin/mono /usr/local/bin/soundbutton/Sound-Button.exe +KillMode=control-group +TimeoutStopSec=5 +Restart=on-failure +StandardOutput=null +StandardError=syslog + +[Install] +WantedBy=multi-user.target diff --git a/Soundplayer.sln b/Soundplayer.sln new file mode 100644 index 0000000..0ec2ecc --- /dev/null +++ b/Soundplayer.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Soundbutton", "Soundbutton\Soundbutton.csproj", "{FD9451F4-CA65-4CF4-8CCC-1E29C0F657A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Posix", "..\Librarys\Mono.Posix\Mono.Posix\Mono.Posix.csproj", "{E2CA132E-E85C-40AD-BE94-B138AA68772B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{8C5D4DE9-377F-4EC8-873D-6EEF15F43516}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.Swan", "..\Librarys\RaspberryIO\Unosquare.Swan\Unosquare.Swan.csproj", "{2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.Swan.Lite", "..\Librarys\RaspberryIO\Unosquare.Swan.Lite\Unosquare.Swan.Lite.csproj", "{AB015683-62E5-47F1-861F-6D037F9C6433}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bot-Utils", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils.csproj", "{BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FD9451F4-CA65-4CF4-8CCC-1E29C0F657A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD9451F4-CA65-4CF4-8CCC-1E29C0F657A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD9451F4-CA65-4CF4-8CCC-1E29C0F657A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD9451F4-CA65-4CF4-8CCC-1E29C0F657A7}.Release|Any CPU.Build.0 = Release|Any CPU + {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Release|Any CPU.Build.0 = Release|Any CPU + {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Release|Any CPU.Build.0 = Release|Any CPU + {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Release|Any CPU.Build.0 = Release|Any CPU + {AB015683-62E5-47F1-861F-6D037F9C6433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB015683-62E5-47F1-861F-6D037F9C6433}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB015683-62E5-47F1-861F-6D037F9C6433}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB015683-62E5-47F1-861F-6D037F9C6433}.Release|Any CPU.Build.0 = Release|Any CPU + {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Release|Any CPU.Build.0 = Release|Any CPU + {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E0BE25E2-1320-4523-8BD7-3A385E946487} + EndGlobalSection +EndGlobal